@plannotator/ui 0.22.0 → 0.23.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.
@@ -212,22 +212,24 @@ export const OpenInAppButton: React.FC<OpenInAppButtonProps> = ({
212
212
  )}
213
213
  {/* Chevron (with primary) or standalone overflow (copy-only). */}
214
214
  <DropdownMenu open={menuOpen} onOpenChange={setMenuOpen}>
215
- <DropdownMenuTrigger asChild>
216
- <button
217
- type="button"
218
- disabled={isDisabled}
219
- className={`text-xs flex items-center py-1 transition-colors text-muted-foreground hover:text-foreground hover:bg-muted disabled:opacity-50 disabled:cursor-not-allowed ${
220
- openable ? 'px-1 border-l border-border/50' : 'px-1.5'
221
- }`}
222
- title={openable ? 'Open in…' : 'File actions'}
223
- aria-label={openable ? 'Choose app to open in' : 'File actions'}
224
- >
225
- {openable ? (
226
- <ChevronDown className="w-3 h-3" />
227
- ) : (
228
- <MoreHorizontal className="w-3.5 h-3.5" />
229
- )}
230
- </button>
215
+ <DropdownMenuTrigger
216
+ render={
217
+ <button
218
+ type="button"
219
+ disabled={isDisabled}
220
+ className={`text-xs flex items-center py-1 transition-colors text-muted-foreground hover:text-foreground hover:bg-muted disabled:opacity-50 disabled:cursor-not-allowed ${
221
+ openable ? 'px-1 border-l border-border/50' : 'px-1.5'
222
+ }`}
223
+ title={openable ? 'Open in…' : 'File actions'}
224
+ aria-label={openable ? 'Choose app to open in' : 'File actions'}
225
+ />
226
+ }
227
+ >
228
+ {openable ? (
229
+ <ChevronDown className="w-3 h-3" />
230
+ ) : (
231
+ <MoreHorizontal className="w-3.5 h-3.5" />
232
+ )}
231
233
  </DropdownMenuTrigger>
232
234
  <DropdownMenuContent
233
235
  align="end"
@@ -235,7 +237,7 @@ export const OpenInAppButton: React.FC<OpenInAppButtonProps> = ({
235
237
  className="min-w-[12rem]"
236
238
  // Don't snap focus (and its focus ring) back onto the trigger when
237
239
  // the menu closes — that left-edge bar reads as a stray artifact.
238
- onCloseAutoFocus={(event) => event.preventDefault()}
240
+ finalFocus={false}
239
241
  >
240
242
  {openable &&
241
243
  grouped.map((group, gi) => (
@@ -244,10 +246,8 @@ export const OpenInAppButton: React.FC<OpenInAppButtonProps> = ({
244
246
  {group.map((app) => (
245
247
  <DropdownMenuItem
246
248
  key={app.id}
247
- onSelect={(e) => {
248
- e.preventDefault();
249
- selectApp(app.id);
250
- }}
249
+ closeOnClick={false}
250
+ onClick={() => selectApp(app.id)}
251
251
  className="text-xs"
252
252
  >
253
253
  <AppIcon id={app.icon} className="w-4 h-4" />
@@ -260,10 +260,8 @@ export const OpenInAppButton: React.FC<OpenInAppButtonProps> = ({
260
260
  {openable && (filePath || diffText) && <DropdownMenuSeparator />}
261
261
  {filePath && (
262
262
  <DropdownMenuItem
263
- onSelect={(e) => {
264
- e.preventDefault();
265
- void copyText(filePath);
266
- }}
263
+ closeOnClick={false}
264
+ onClick={() => void copyText(filePath)}
267
265
  className="text-xs"
268
266
  >
269
267
  <Copy className="w-4 h-4" />
@@ -272,10 +270,8 @@ export const OpenInAppButton: React.FC<OpenInAppButtonProps> = ({
272
270
  )}
273
271
  {diffText && (
274
272
  <DropdownMenuItem
275
- onSelect={(e) => {
276
- e.preventDefault();
277
- void copyText(diffText);
278
- }}
273
+ closeOnClick={false}
274
+ onClick={() => void copyText(diffText)}
279
275
  className="text-xs"
280
276
  >
281
277
  <Copy className="w-4 h-4" />
@@ -1,5 +1,5 @@
1
1
  import React, { useCallback } from 'react';
2
- import * as Dialog from '@radix-ui/react-dialog';
2
+ import { Dialog } from '@base-ui/react/dialog';
3
3
 
4
4
  const ANNOTATION_SELECTORS = [
5
5
  '.annotation-toolbar',
@@ -14,7 +14,7 @@ interface PopoutDialogProps {
14
14
  container?: HTMLElement | null;
15
15
  className?: string;
16
16
  children: React.ReactNode;
17
- /** Extra data attributes to spread onto Dialog.Content */
17
+ /** Extra data attributes to spread onto the dialog popup */
18
18
  dataAttributes?: Record<string, string>;
19
19
  }
20
20
 
@@ -36,55 +36,69 @@ export const PopoutDialog: React.FC<PopoutDialogProps> = ({
36
36
  [onClose],
37
37
  );
38
38
 
39
- const handleInteractOutside = useCallback(
40
- (e: Event) => {
41
- const target = e.target as Element | null;
42
- if (!target) return;
43
- if (ANNOTATION_SELECTORS.some((sel) => target.closest(sel))) {
44
- e.preventDefault();
39
+ const handleOpenChange = useCallback(
40
+ (next: boolean, eventDetails: Dialog.Root.ChangeEventDetails) => {
41
+ if (next) return;
42
+ // Interactions with annotation UI (toolbars/popovers portal outside the
43
+ // dialog) must not dismiss the popout — the Radix version guarded this
44
+ // via onInteractOutside preventDefault; Base UI expresses it as
45
+ // cancelling the outside-press/focus-out close reason.
46
+ if (eventDetails.reason === 'outside-press' || eventDetails.reason === 'focus-out') {
47
+ // For focus events the annotation UI may sit on either side of the
48
+ // event (target = element losing focus, relatedTarget = gaining), so
49
+ // guard both.
50
+ const event = eventDetails.event as Event | undefined;
51
+ const candidates = [
52
+ event?.target as Element | null,
53
+ (event as FocusEvent | undefined)?.relatedTarget as Element | null,
54
+ ];
55
+ if (
56
+ candidates.some(
57
+ (el) => el instanceof Element && ANNOTATION_SELECTORS.some((sel) => el.closest(sel)),
58
+ )
59
+ ) {
60
+ eventDetails.cancel();
61
+ return;
62
+ }
45
63
  }
64
+ onClose();
46
65
  },
47
- [],
66
+ [onClose],
48
67
  );
49
68
 
50
69
  return (
51
- <Dialog.Root
52
- open={open}
53
- onOpenChange={(next) => { if (!next) onClose(); }}
54
- modal={false}
55
- >
70
+ <Dialog.Root open={open} onOpenChange={handleOpenChange} modal={false}>
56
71
  <Dialog.Portal container={container ?? undefined}>
57
- {/* Radix ignores Dialog.Overlay when modal={false}, so we use a plain
58
- div for the backdrop. This gives us the dark scrim + blur while
59
- keeping annotation toolbars (which portal outside the dialog)
60
- interactive. */}
72
+ {/* Non-modal dialogs render no library backdrop, so we use a plain
73
+ div for the dark scrim + blur while keeping annotation toolbars
74
+ (which portal outside the dialog) interactive. */}
61
75
  <div
62
76
  className="fixed inset-0 z-50 bg-black/50 backdrop-blur-[2px]"
63
77
  onClick={handleBackdropClick}
64
78
  aria-hidden="true"
65
79
  />
66
- <Dialog.Content
80
+ <Dialog.Popup
67
81
  className={`fixed left-1/2 top-1/2 z-50 -translate-x-1/2 -translate-y-1/2 bg-background border border-border rounded-xl shadow-2xl flex flex-col overflow-hidden ${className ?? 'w-[calc(100vw-4rem)] max-w-[min(calc(100vw-4rem),1500px)] max-h-[calc(100vh-4rem)]'}`}
68
82
  data-popout="true"
69
- aria-describedby={undefined}
70
- onOpenAutoFocus={(e) => e.preventDefault()}
71
- onInteractOutside={handleInteractOutside}
83
+ initialFocus={false}
72
84
  {...dataAttributes}
73
85
  >
74
86
  <Dialog.Title className="sr-only">{title}</Dialog.Title>
75
- <Dialog.Close asChild>
76
- <button
77
- className="absolute top-3 right-3 z-20 p-1.5 rounded-md text-muted-foreground/70 hover:bg-muted hover:text-foreground transition-colors"
78
- aria-label="Close"
79
- >
80
- <svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
81
- <path strokeLinecap="round" strokeLinejoin="round" d="M6 18L18 6M6 6l12 12" />
82
- </svg>
83
- </button>
87
+ <Dialog.Close
88
+ render={
89
+ <button
90
+ className="absolute top-3 right-3 z-20 p-1.5 rounded-md text-muted-foreground/70 hover:bg-muted hover:text-foreground transition-colors"
91
+ aria-label="Close"
92
+ />
93
+ }
94
+ >
95
+ <svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
96
+ <path strokeLinecap="round" strokeLinejoin="round" d="M6 18L18 6M6 6l12 12" />
97
+ </svg>
84
98
  </Dialog.Close>
85
99
 
86
100
  {children}
87
- </Dialog.Content>
101
+ </Dialog.Popup>
88
102
  </Dialog.Portal>
89
103
  </Dialog.Root>
90
104
  );
@@ -1,27 +1,33 @@
1
- import * as PopoverPrimitive from '@radix-ui/react-popover';
1
+ import { Popover as PopoverPrimitive } from '@base-ui/react/popover';
2
2
  import React from 'react';
3
3
 
4
4
  const Popover = PopoverPrimitive.Root;
5
5
  const PopoverTrigger = PopoverPrimitive.Trigger;
6
- const PopoverAnchor = PopoverPrimitive.Anchor;
7
6
 
8
7
  const PopoverContent = React.forwardRef<
9
- React.ComponentRef<typeof PopoverPrimitive.Content>,
10
- React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>
11
- >(({ className, align = 'center', sideOffset = 6, children, ...props }, ref) => (
8
+ HTMLDivElement,
9
+ PopoverPrimitive.Popup.Props &
10
+ Pick<PopoverPrimitive.Positioner.Props, 'side' | 'sideOffset' | 'align' | 'alignOffset'>
11
+ >(({ className, side, align = 'center', sideOffset = 6, alignOffset, children, ...props }, ref) => (
12
12
  <PopoverPrimitive.Portal>
13
- <PopoverPrimitive.Content
14
- ref={ref}
13
+ <PopoverPrimitive.Positioner
14
+ side={side}
15
15
  align={align}
16
16
  sideOffset={sideOffset}
17
- className={`bg-popover text-popover-foreground border border-border/50 rounded-lg shadow-xl z-[100] outline-none popover-enter ${className ?? ''}`}
18
- {...props}
17
+ alignOffset={alignOffset}
18
+ className="isolate z-[100]"
19
19
  >
20
- {children}
21
- </PopoverPrimitive.Content>
20
+ <PopoverPrimitive.Popup
21
+ ref={ref}
22
+ className={`bg-popover text-popover-foreground border border-border/50 rounded-lg shadow-xl z-[100] outline-none origin-[var(--transform-origin)] transition-[opacity,scale] duration-150 ease-out data-[starting-style]:opacity-0 data-[starting-style]:scale-95 data-[ending-style]:opacity-0 data-[ending-style]:scale-95 ${className ?? ''}`}
23
+ {...props}
24
+ >
25
+ {children}
26
+ </PopoverPrimitive.Popup>
27
+ </PopoverPrimitive.Positioner>
22
28
  </PopoverPrimitive.Portal>
23
29
  ));
24
30
 
25
31
  PopoverContent.displayName = 'PopoverContent';
26
32
 
27
- export { Popover, PopoverTrigger, PopoverContent, PopoverAnchor };
33
+ export { Popover, PopoverTrigger, PopoverContent };
@@ -1,4 +1,4 @@
1
- import React, { useState, useMemo, useRef, useCallback, type ReactNode } from 'react';
1
+ import React, { useState, useMemo, useRef, useCallback, type ReactElement, type ReactNode } from 'react';
2
2
  import { Popover, PopoverTrigger, PopoverContent } from './Popover';
3
3
 
4
4
  interface SearchableSelectProps<T extends { id: string }> {
@@ -7,7 +7,7 @@ interface SearchableSelectProps<T extends { id: string }> {
7
7
  onSelect: (item: T) => void;
8
8
  filterFn: (item: T, query: string) => boolean;
9
9
  renderItem: (item: T, state: { isSelected: boolean; isFocused: boolean }) => ReactNode;
10
- renderTrigger: (state: { open: boolean }) => ReactNode;
10
+ renderTrigger: (state: { open: boolean }) => ReactElement;
11
11
  headerContent?: ReactNode;
12
12
  placeholder?: string;
13
13
  emptyMessage?: string;
@@ -85,14 +85,11 @@ export function SearchableSelect<T extends { id: string }>({
85
85
 
86
86
  return (
87
87
  <Popover open={open} onOpenChange={handleOpenChange}>
88
- <PopoverTrigger asChild>{renderTrigger({ open })}</PopoverTrigger>
88
+ <PopoverTrigger render={renderTrigger({ open })} />
89
89
  <PopoverContent
90
90
  align={align}
91
91
  className={`${width} p-0`}
92
- onOpenAutoFocus={(e) => {
93
- e.preventDefault();
94
- inputRef.current?.focus();
95
- }}
92
+ initialFocus={inputRef}
96
93
  >
97
94
  {/* Search row */}
98
95
  <div className="flex items-center gap-2 border-b border-border/50 px-3 py-2">
@@ -1,11 +1,39 @@
1
1
  import React from 'react';
2
- import * as RadixTooltip from '@radix-ui/react-tooltip';
2
+ import { Tooltip as BaseTooltip } from '@base-ui/react/tooltip';
3
3
 
4
- export const TooltipProvider = RadixTooltip.Provider;
4
+ /**
5
+ * TooltipProvider keeps the Radix-era prop names (`delayDuration`,
6
+ * `skipDelayDuration`, `disableHoverableContent`) as its public API and maps
7
+ * them onto Base UI's Provider (`delay`, `timeout`) — call sites in the apps
8
+ * stay unchanged. `disableHoverableContent` has no provider-level equivalent
9
+ * in Base UI (it moved to per-root `disableHoverablePopup`), so it is carried
10
+ * via context and applied to every Tooltip root under the provider.
11
+ */
12
+ const DisableHoverablePopupContext = React.createContext(false);
13
+
14
+ interface TooltipProviderProps {
15
+ delayDuration?: number;
16
+ skipDelayDuration?: number;
17
+ disableHoverableContent?: boolean;
18
+ children?: React.ReactNode;
19
+ }
20
+
21
+ export const TooltipProvider: React.FC<TooltipProviderProps> = ({
22
+ delayDuration,
23
+ skipDelayDuration,
24
+ disableHoverableContent = false,
25
+ children,
26
+ }) => (
27
+ <BaseTooltip.Provider delay={delayDuration} timeout={skipDelayDuration}>
28
+ <DisableHoverablePopupContext.Provider value={disableHoverableContent}>
29
+ {children}
30
+ </DisableHoverablePopupContext.Provider>
31
+ </BaseTooltip.Provider>
32
+ );
5
33
 
6
34
  interface TooltipProps {
7
35
  content: React.ReactNode;
8
- children: React.ReactNode;
36
+ children: React.ReactElement;
9
37
  side?: 'top' | 'right' | 'bottom' | 'left';
10
38
  align?: 'start' | 'center' | 'end';
11
39
  delayDuration?: number;
@@ -26,20 +54,22 @@ export const Tooltip: React.FC<TooltipProps> = ({
26
54
  delayDuration,
27
55
  sideOffset = 8,
28
56
  wide = false,
29
- }) => (
30
- <RadixTooltip.Root delayDuration={delayDuration}>
31
- <RadixTooltip.Trigger asChild>{children}</RadixTooltip.Trigger>
32
- <RadixTooltip.Portal>
33
- <RadixTooltip.Content
34
- side={side}
35
- align={align}
36
- sideOffset={sideOffset}
37
- className={`z-50 px-2 py-1 text-xs bg-popover text-popover-foreground border border-border rounded shadow-md origin-[var(--radix-tooltip-content-transform-origin)] transition-[opacity,transform] duration-150 ease-out data-[state=closed]:opacity-0 data-[state=closed]:scale-95 data-[state=delayed-open]:opacity-100 data-[state=delayed-open]:scale-100 data-[state=instant-open]:opacity-100 data-[state=instant-open]:scale-100 ${
38
- wide ? 'max-w-[260px] leading-snug whitespace-normal' : 'whitespace-nowrap'
39
- }`}
40
- >
41
- {content}
42
- </RadixTooltip.Content>
43
- </RadixTooltip.Portal>
44
- </RadixTooltip.Root>
45
- );
57
+ }) => {
58
+ const disableHoverablePopup = React.useContext(DisableHoverablePopupContext);
59
+ return (
60
+ <BaseTooltip.Root disableHoverablePopup={disableHoverablePopup}>
61
+ <BaseTooltip.Trigger render={children} delay={delayDuration} />
62
+ <BaseTooltip.Portal>
63
+ <BaseTooltip.Positioner side={side} align={align} sideOffset={sideOffset} className="isolate z-50">
64
+ <BaseTooltip.Popup
65
+ className={`z-50 px-2 py-1 text-xs bg-popover text-popover-foreground border border-border rounded shadow-md origin-[var(--transform-origin)] transition-[opacity,scale] duration-150 ease-out data-[starting-style]:opacity-0 data-[starting-style]:scale-95 data-[ending-style]:opacity-0 data-[ending-style]:scale-95 ${
66
+ wide ? 'max-w-[260px] leading-snug whitespace-normal' : 'whitespace-nowrap'
67
+ }`}
68
+ >
69
+ {content}
70
+ </BaseTooltip.Popup>
71
+ </BaseTooltip.Positioner>
72
+ </BaseTooltip.Portal>
73
+ </BaseTooltip.Root>
74
+ );
75
+ };
@@ -1,4 +1,5 @@
1
- import { Slot } from "@radix-ui/react-slot";
1
+ import { mergeProps } from "@base-ui/react/merge-props";
2
+ import { useRender } from "@base-ui/react/use-render";
2
3
  import { cva, type VariantProps } from "class-variance-authority";
3
4
  import type * as React from "react";
4
5
 
@@ -6,8 +7,9 @@ import { cn } from "../../lib/utils";
6
7
 
7
8
  /**
8
9
  * Badge — small labelled token (status, category, count). Token-driven variants.
9
- * Pass `asChild` to render as a link/button. Override padding/size via className
10
- * for tighter inline badges (e.g. `px-1.5 py-px text-[10px]`).
10
+ * Pass `render` (e.g. `render={<a href=... />}`) to render as a link/button.
11
+ * Override padding/size via className for tighter inline badges
12
+ * (e.g. `px-1.5 py-px text-[10px]`).
11
13
  */
12
14
  const badgeVariants = cva(
13
15
  "inline-flex w-fit shrink-0 items-center justify-center gap-1 overflow-auto whitespace-nowrap rounded-md border px-3 py-1 text-xs font-medium transition-[color,box-shadow] [&>svg]:size-3 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40",
@@ -31,14 +33,17 @@ const badgeVariants = cva(
31
33
  function Badge({
32
34
  className,
33
35
  variant,
34
- asChild = false,
36
+ render,
35
37
  ...props
36
- }: React.ComponentProps<"span"> & VariantProps<typeof badgeVariants> & { asChild?: boolean }) {
37
- const Comp = asChild ? Slot : "span";
38
-
39
- return (
40
- <Comp data-slot="badge" className={cn(badgeVariants({ variant }), className)} {...props} />
41
- );
38
+ }: useRender.ComponentProps<"span"> & VariantProps<typeof badgeVariants>) {
39
+ return useRender({
40
+ defaultTagName: "span",
41
+ render,
42
+ props: mergeProps<"span">(
43
+ { "data-slot": "badge", className: cn(badgeVariants({ variant }), className) } as React.ComponentProps<"span">,
44
+ props,
45
+ ),
46
+ });
42
47
  }
43
48
 
44
49
  export { Badge, badgeVariants };
@@ -1,4 +1,4 @@
1
- import { Slot, Slottable } from "@radix-ui/react-slot";
1
+ import { Button as ButtonPrimitive } from "@base-ui/react/button";
2
2
  import { cva, type VariantProps } from "class-variance-authority";
3
3
  import type * as React from "react";
4
4
 
@@ -7,7 +7,7 @@ import { cn } from "../../lib/utils";
7
7
  /**
8
8
  * Button — the canonical action primitive (shared by the frontend shell and the
9
9
  * embedded plan/review apps). cva variants + sizes, optional `iconLeft`/`iconRight`
10
- * slots, and `asChild` for polymorphism.
10
+ * slots, and Base UI's `render` prop for polymorphism (e.g. `render={<a href=... />}`).
11
11
  *
12
12
  * `success` (solid, token-driven green) covers the plan app's Approve action; the
13
13
  * Feedback action uses `outline`. (No `accent` variant — `text-accent` on `bg-accent`
@@ -51,32 +51,32 @@ function Button({
51
51
  className,
52
52
  variant,
53
53
  size,
54
- asChild = false,
55
54
  iconLeft,
56
55
  iconRight,
57
56
  ...props
58
- }: React.ComponentProps<"button"> &
57
+ }: ButtonPrimitive.Props &
59
58
  VariantProps<typeof buttonVariants> & {
60
- asChild?: boolean;
61
59
  iconLeft?: ButtonIcon;
62
60
  iconRight?: ButtonIcon;
63
61
  }) {
64
- const Comp = asChild ? Slot : "button";
65
-
66
62
  return (
67
- <Comp data-slot="button" className={cn(buttonVariants({ variant, size, className }))} {...props}>
63
+ <ButtonPrimitive
64
+ data-slot="button"
65
+ className={cn(buttonVariants({ variant, size, className }))}
66
+ {...props}
67
+ >
68
68
  {iconLeft ? (
69
69
  <span data-slot="button-icon" data-side="left" aria-hidden="true" className="shrink-0">
70
70
  {iconLeft}
71
71
  </span>
72
72
  ) : null}
73
- <Slottable>{children}</Slottable>
73
+ {children}
74
74
  {iconRight ? (
75
75
  <span data-slot="button-icon" data-side="right" aria-hidden="true" className="shrink-0">
76
76
  {iconRight}
77
77
  </span>
78
78
  ) : null}
79
- </Comp>
79
+ </ButtonPrimitive>
80
80
  );
81
81
  }
82
82
 
@@ -1,5 +1,5 @@
1
1
  import * as React from "react";
2
- import * as DialogPrimitive from "@radix-ui/react-dialog";
2
+ import { Dialog as DialogPrimitive } from "@base-ui/react/dialog";
3
3
  import { X } from "lucide-react";
4
4
  import { cn } from "../../lib/utils";
5
5
 
@@ -9,31 +9,31 @@ const DialogPortal = DialogPrimitive.Portal;
9
9
  const DialogClose = DialogPrimitive.Close;
10
10
 
11
11
  const DialogOverlay = React.forwardRef<
12
- React.ComponentRef<typeof DialogPrimitive.Overlay>,
13
- React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>
12
+ React.ComponentRef<typeof DialogPrimitive.Backdrop>,
13
+ React.ComponentPropsWithoutRef<typeof DialogPrimitive.Backdrop>
14
14
  >(({ className, ...props }, ref) => (
15
- <DialogPrimitive.Overlay
15
+ <DialogPrimitive.Backdrop
16
16
  ref={ref}
17
17
  className={cn(
18
18
  "fixed inset-0 z-[110] bg-black/55 backdrop-blur-[2px]",
19
- "data-[state=open]:animate-in data-[state=open]:fade-in-0",
20
- "data-[state=closed]:animate-out data-[state=closed]:fade-out-0",
19
+ "transition-opacity duration-200",
20
+ "data-starting-style:opacity-0 data-ending-style:opacity-0",
21
21
  className,
22
22
  )}
23
23
  {...props}
24
24
  />
25
25
  ));
26
- DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
26
+ DialogOverlay.displayName = "DialogOverlay";
27
27
 
28
28
  const DialogContent = React.forwardRef<
29
- React.ComponentRef<typeof DialogPrimitive.Content>,
30
- React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content> & {
29
+ React.ComponentRef<typeof DialogPrimitive.Popup>,
30
+ React.ComponentPropsWithoutRef<typeof DialogPrimitive.Popup> & {
31
31
  hideClose?: boolean;
32
32
  }
33
33
  >(({ className, children, hideClose, ...props }, ref) => (
34
34
  <DialogPortal>
35
35
  <DialogOverlay />
36
- <DialogPrimitive.Content
36
+ <DialogPrimitive.Popup
37
37
  ref={ref}
38
38
  className={cn(
39
39
  "fixed top-[50%] left-[50%] z-[110] w-full translate-x-[-50%] translate-y-[-50%]",
@@ -41,9 +41,9 @@ const DialogContent = React.forwardRef<
41
41
  "flex flex-col overflow-hidden",
42
42
  "rounded-2xl border border-border bg-popover text-popover-foreground",
43
43
  "shadow-[0_24px_80px_-36px_rgba(15,23,42,0.5)]",
44
- "data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
45
- "data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
46
- "duration-200",
44
+ "transition-[opacity,scale] duration-200",
45
+ "data-starting-style:opacity-0 data-starting-style:scale-95",
46
+ "data-ending-style:opacity-0 data-ending-style:scale-95",
47
47
  className,
48
48
  )}
49
49
  {...props}
@@ -55,10 +55,10 @@ const DialogContent = React.forwardRef<
55
55
  <span className="sr-only">Close</span>
56
56
  </DialogPrimitive.Close>
57
57
  )}
58
- </DialogPrimitive.Content>
58
+ </DialogPrimitive.Popup>
59
59
  </DialogPortal>
60
60
  ));
61
- DialogContent.displayName = DialogPrimitive.Content.displayName;
61
+ DialogContent.displayName = "DialogContent";
62
62
 
63
63
  function DialogHeader({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {
64
64
  return (
@@ -79,7 +79,7 @@ const DialogTitle = React.forwardRef<
79
79
  {...props}
80
80
  />
81
81
  ));
82
- DialogTitle.displayName = DialogPrimitive.Title.displayName;
82
+ DialogTitle.displayName = "DialogTitle";
83
83
 
84
84
  const DialogDescription = React.forwardRef<
85
85
  React.ComponentRef<typeof DialogPrimitive.Description>,
@@ -91,7 +91,7 @@ const DialogDescription = React.forwardRef<
91
91
  {...props}
92
92
  />
93
93
  ));
94
- DialogDescription.displayName = DialogPrimitive.Description.displayName;
94
+ DialogDescription.displayName = "DialogDescription";
95
95
 
96
96
  export {
97
97
  Dialog,