@flamingo-stack/openframe-frontend-core 0.0.755 → 0.0.756

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 (87) hide show
  1. package/dist/{chunk-AG4HR6Z6.cjs → chunk-2ANICXS7.cjs} +16 -16
  2. package/dist/{chunk-HSWNJAIK.cjs → chunk-4YL4Y3BV.cjs} +11 -11
  3. package/dist/{chunk-HAL6HBTM.cjs → chunk-57JA37HP.cjs} +428 -411
  4. package/dist/{chunk-32IKIBPY.cjs → chunk-7KPU7RGS.cjs} +73 -73
  5. package/dist/{chunk-MGF3FUKD.cjs → chunk-AKK3EO37.cjs} +4 -1
  6. package/dist/{chunk-3GG3QAPT.cjs → chunk-AXBVN5SW.cjs} +63 -57
  7. package/dist/{chunk-RRCHQTZW.cjs → chunk-BTIYXBA2.cjs} +4 -4
  8. package/dist/{chunk-BQ5KRCSJ.cjs → chunk-CYDWQYIQ.cjs} +22 -22
  9. package/dist/{chunk-P6F6PHVK.cjs → chunk-EFTUFJS2.cjs} +4 -4
  10. package/dist/{chunk-LVO7FALW.cjs → chunk-F64VMOIB.cjs} +5 -5
  11. package/dist/{chunk-Q2MSW2IW.cjs → chunk-KFUC2XF7.cjs} +7 -7
  12. package/dist/{chunk-5WHEQ63L.cjs → chunk-KNNJ4WLF.cjs} +4 -4
  13. package/dist/{chunk-RRE6C3ZU.cjs → chunk-KSU3CXKY.cjs} +3 -3
  14. package/dist/{chunk-YRULLK7N.cjs → chunk-LOFDIDSD.cjs} +8 -2
  15. package/dist/{chunk-JV4VVA2V.cjs → chunk-MBQTLZAG.cjs} +11 -11
  16. package/dist/{chunk-BVEUGFIN.cjs → chunk-MDXZMTCK.cjs} +38 -38
  17. package/dist/{chunk-FOVNP5HU.cjs → chunk-MR5KMPSE.cjs} +6 -6
  18. package/dist/{chunk-NS5DO6QK.cjs → chunk-PUK27ZB6.cjs} +22 -22
  19. package/dist/{chunk-NE3T3ZIG.cjs → chunk-QKFJ6ORK.cjs} +21 -21
  20. package/dist/{chunk-SDF5UUTE.cjs → chunk-QTYSYEHK.cjs} +74 -74
  21. package/dist/{chunk-YXX6UMG3.cjs → chunk-TAEEGNFL.cjs} +42 -42
  22. package/dist/{chunk-SZGUEPJC.cjs → chunk-VOXDBCBV.cjs} +36 -36
  23. package/dist/{chunk-UNRNLSG4.cjs → chunk-VUSXDMCE.cjs} +2 -2
  24. package/dist/{chunk-2HWKYPJB.cjs → chunk-W5MEHJRQ.cjs} +6 -6
  25. package/dist/{cloud-tenants-S7RR2UDJ.cjs → cloud-tenants-NOZGXQZY.cjs} +10 -10
  26. package/dist/components/case-studies/index.cjs +20 -20
  27. package/dist/components/chat/index.cjs +7 -7
  28. package/dist/components/contact/index.cjs +11 -11
  29. package/dist/components/context-menu.d.ts +2 -2
  30. package/dist/components/context-menu.d.ts.map +1 -1
  31. package/dist/components/context-menu.js +19 -12
  32. package/dist/components/docs/index.cjs +14 -14
  33. package/dist/components/embeds/index.cjs +11 -11
  34. package/dist/components/faq/index.cjs +12 -12
  35. package/dist/components/features/index.cjs +10 -10
  36. package/dist/components/features/time-tracker/time-tracker-header-button.d.ts.map +1 -1
  37. package/dist/components/features/time-tracker/time-tracker-header-button.js +3 -1
  38. package/dist/components/help-center-pages/index.cjs +71 -71
  39. package/dist/components/index.cjs +44 -44
  40. package/dist/components/meeting-scheduler/index.cjs +35 -35
  41. package/dist/components/navigation/index.cjs +13 -13
  42. package/dist/components/onboarding-guides/index.cjs +13 -13
  43. package/dist/components/popover.d.ts.map +1 -1
  44. package/dist/components/popover.js +3 -1
  45. package/dist/components/product-demo/index.cjs +9 -9
  46. package/dist/components/tickets/index.cjs +15 -15
  47. package/dist/components/ui/date-picker.d.ts.map +1 -1
  48. package/dist/components/ui/date-picker.js +9 -4
  49. package/dist/components/ui/dropdown-menu.d.ts +2 -2
  50. package/dist/components/ui/dropdown-menu.d.ts.map +1 -1
  51. package/dist/components/ui/dropdown-menu.js +4 -1
  52. package/dist/components/ui/file-manager/index.cjs +6 -6
  53. package/dist/components/ui/index.cjs +10 -10
  54. package/dist/components/ui/menubar.d.ts +2 -2
  55. package/dist/components/ui/menubar.d.ts.map +1 -1
  56. package/dist/components/ui/menubar.js +22 -15
  57. package/dist/components/ui/modal-v2.d.ts.map +1 -1
  58. package/dist/components/ui/modal-v2.js +5 -2
  59. package/dist/components/ui/searchable-select.d.ts.map +1 -1
  60. package/dist/components/ui/searchable-select.js +3 -1
  61. package/dist/components/ui/select.d.ts.map +1 -1
  62. package/dist/components/ui/select.js +27 -23
  63. package/dist/components/ui/tag-select-dropdown.d.ts.map +1 -1
  64. package/dist/components/ui/tag-select-dropdown.js +3 -1
  65. package/dist/{devices-KCD2WSEV.cjs → devices-M4KBTOTC.cjs} +11 -11
  66. package/dist/{embeddable-chat-OGUGNKLP.cjs → embeddable-chat-KGJVVG2V.cjs} +77 -77
  67. package/dist/index.cjs +14 -14
  68. package/dist/{knowledge-OX5PYEPE.cjs → knowledge-VVF6CJEG.cjs} +11 -11
  69. package/dist/{logs-ZVOBADLB.cjs → logs-7E6HBJ55.cjs} +18 -18
  70. package/dist/{policies-NSHPEZTR.cjs → policies-UMZLJTBD.cjs} +14 -14
  71. package/dist/{remote-session-57DGC4X3.cjs → remote-session-SKNXYG6K.cjs} +7 -7
  72. package/dist/{scripts-OHMKBEXO.cjs → scripts-XVNAEYCH.cjs} +17 -17
  73. package/dist/{software-update-WMLGMSBQ.cjs → software-update-U43ZFHMC.cjs} +14 -14
  74. package/dist/{tickets-board-EP6L3BSV.cjs → tickets-board-B2FH7Z4B.cjs} +9 -9
  75. package/eslint-config/base.js +7 -1
  76. package/eslint-config/popup-portal.js +68 -0
  77. package/package.json +1 -1
  78. package/src/components/context-menu.tsx +20 -13
  79. package/src/components/features/time-tracker/time-tracker-header-button.tsx +3 -1
  80. package/src/components/popover.tsx +3 -1
  81. package/src/components/ui/date-picker.tsx +9 -4
  82. package/src/components/ui/dropdown-menu.tsx +4 -1
  83. package/src/components/ui/menubar.tsx +23 -16
  84. package/src/components/ui/modal-v2.tsx +17 -3
  85. package/src/components/ui/searchable-select.tsx +3 -1
  86. package/src/components/ui/select.tsx +28 -24
  87. package/src/components/ui/tag-select-dropdown.tsx +3 -1
@@ -5,6 +5,7 @@ import { Check, ChevronRight, Circle } from 'lucide-react';
5
5
  import { type ComponentPropsWithoutRef, type ElementRef, type HTMLAttributes, forwardRef } from 'react';
6
6
 
7
7
  import { cn } from '../utils/cn';
8
+ import { usePortalContainer } from './ui/portal-container';
8
9
 
9
10
  const ContextMenu = ContextMenuPrimitive.Root;
10
11
 
@@ -12,7 +13,10 @@ const ContextMenuTrigger = ContextMenuPrimitive.Trigger;
12
13
 
13
14
  const ContextMenuGroup = ContextMenuPrimitive.Group;
14
15
 
15
- const ContextMenuPortal = ContextMenuPrimitive.Portal;
16
+ function ContextMenuPortal({ container, ...props }: ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Portal>) {
17
+ const active = usePortalContainer();
18
+ return <ContextMenuPrimitive.Portal container={container ?? active ?? undefined} {...props} />;
19
+ }
16
20
 
17
21
  const ContextMenuSub = ContextMenuPrimitive.Sub;
18
22
 
@@ -57,18 +61,21 @@ ContextMenuSubContent.displayName = ContextMenuPrimitive.SubContent.displayName;
57
61
  const ContextMenuContent = forwardRef<
58
62
  ElementRef<typeof ContextMenuPrimitive.Content>,
59
63
  ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Content>
60
- >(({ className, ...props }, ref) => (
61
- <ContextMenuPrimitive.Portal>
62
- <ContextMenuPrimitive.Content
63
- ref={ref}
64
- className={cn(
65
- 'z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md animate-in fade-in-80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
66
- className,
67
- )}
68
- {...props}
69
- />
70
- </ContextMenuPrimitive.Portal>
71
- ));
64
+ >(({ className, ...props }, ref) => {
65
+ const container = usePortalContainer();
66
+ return (
67
+ <ContextMenuPrimitive.Portal container={container ?? undefined}>
68
+ <ContextMenuPrimitive.Content
69
+ ref={ref}
70
+ className={cn(
71
+ 'z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md animate-in fade-in-80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
72
+ className,
73
+ )}
74
+ {...props}
75
+ />
76
+ </ContextMenuPrimitive.Portal>
77
+ );
78
+ });
72
79
  ContextMenuContent.displayName = ContextMenuPrimitive.Content.displayName;
73
80
 
74
81
  const ContextMenuItem = forwardRef<
@@ -11,6 +11,7 @@ import {
11
11
  } from '../../navigation/app-layout-context';
12
12
  import { HeaderButton } from '../../navigation/header-button';
13
13
  import { OVERLAY_BACKDROP_CLASS } from '../../ui/drawer';
14
+ import { usePortalContainer } from '../../ui/portal-container';
14
15
  import { useOptionalTimeTracker } from './time-tracker-context';
15
16
  import { TimeTrackerPanel } from './time-tracker-panel';
16
17
  import { useTrackerClock } from './use-tracker-clock';
@@ -39,6 +40,7 @@ export function TimeTrackerHeaderButton({ className, disabled }: TimeTrackerHead
39
40
  accumulatedMs: ctx?.accumulatedMs,
40
41
  });
41
42
  const layoutContainer = useAppLayoutDrawerContainer();
43
+ const portalContainer = usePortalContainer();
42
44
  const coordination = useAppLayoutDrawerCoordination();
43
45
 
44
46
  const isOpen = ctx?.isOpen ?? false;
@@ -129,7 +131,7 @@ export function TimeTrackerHeaderButton({ className, disabled }: TimeTrackerHead
129
131
  )}
130
132
  />
131
133
  </PopoverPrimitive.Portal>
132
- <PopoverPrimitive.Portal>
134
+ <PopoverPrimitive.Portal container={portalContainer ?? undefined}>
133
135
  <PopoverPrimitive.Content
134
136
  align="end"
135
137
  sideOffset={8}
@@ -5,6 +5,7 @@ import { type ComponentPropsWithoutRef, type ElementRef, forwardRef } from 'reac
5
5
 
6
6
  import { useKeyboardCollisionPadding } from '../hooks/ui/use-keyboard-collision-padding';
7
7
  import { cn } from '../utils/cn';
8
+ import { usePortalContainer } from './ui/portal-container';
8
9
 
9
10
  const Popover = PopoverPrimitive.Root;
10
11
 
@@ -18,8 +19,9 @@ const PopoverContent = forwardRef<
18
19
  // box — is positioned against a collision viewport that does not know the
19
20
  // software keyboard exists. See useKeyboardCollisionPadding.
20
21
  const keyboardPadding = useKeyboardCollisionPadding();
22
+ const container = usePortalContainer();
21
23
  return (
22
- <PopoverPrimitive.Portal>
24
+ <PopoverPrimitive.Portal container={container ?? undefined}>
23
25
  <PopoverPrimitive.Content
24
26
  ref={ref}
25
27
  align={align}
@@ -9,6 +9,7 @@ import { cn } from '../../utils/cn';
9
9
  import { formatDateWithTimezone, VIEWER_TIMEZONE } from '../../utils/format';
10
10
  import { Button } from './button';
11
11
  import { FieldWrapper } from './field-wrapper';
12
+ import { usePortalContainer } from './portal-container';
12
13
  import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from './select';
13
14
  import type { SortDirection } from './sort-column-item';
14
15
 
@@ -677,6 +678,7 @@ export function DatePicker(props: DatePickerProps) {
677
678
  } = props;
678
679
 
679
680
  const [open, setOpen] = useState(false);
681
+ const portalContainer = usePortalContainer();
680
682
  const isInvalid = invalid || !!error;
681
683
 
682
684
  const displayValue = useMemo(() => {
@@ -730,7 +732,7 @@ export function DatePicker(props: DatePickerProps) {
730
732
  </button>
731
733
  </Popover.Trigger>
732
734
 
733
- <Popover.Portal>
735
+ <Popover.Portal container={portalContainer ?? undefined}>
734
736
  <Popover.Content
735
737
  className={cn(
736
738
  'z-[9999]',
@@ -809,6 +811,7 @@ export function DatePickerInput(props: DatePickerInputProps) {
809
811
  invalid = false,
810
812
  } = props;
811
813
  const [open, setOpen] = useState(false);
814
+ const portalContainer = usePortalContainer();
812
815
  const isInvalid = invalid || !!error;
813
816
 
814
817
  const displayValue = value ? formatDate(value) : '';
@@ -913,7 +916,7 @@ export function DatePickerInput(props: DatePickerInputProps) {
913
916
  </button>
914
917
  </Popover.Trigger>
915
918
 
916
- <Popover.Portal>
919
+ <Popover.Portal container={portalContainer ?? undefined}>
917
920
  <Popover.Content
918
921
  className={cn(
919
922
  'z-[9999]',
@@ -1057,6 +1060,7 @@ export function DatePickerInputSimple(props: DatePickerInputSimpleProps) {
1057
1060
  invalid = false,
1058
1061
  } = props;
1059
1062
  const [open, setOpen] = useState(false);
1063
+ const portalContainer = usePortalContainer();
1060
1064
  const isInvalid = invalid || !!error;
1061
1065
 
1062
1066
  const displayValue = value ? formatDate(value) : '';
@@ -1139,7 +1143,7 @@ export function DatePickerInputSimple(props: DatePickerInputSimpleProps) {
1139
1143
  </button>
1140
1144
  </Popover.Trigger>
1141
1145
 
1142
- <Popover.Portal>
1146
+ <Popover.Portal container={portalContainer ?? undefined}>
1143
1147
  <Popover.Content
1144
1148
  className={cn(
1145
1149
  'z-[9999]',
@@ -1350,6 +1354,7 @@ export function DateFilterMenu({
1350
1354
  'aria-label': ariaLabel = 'Open date filter',
1351
1355
  }: DateFilterMenuProps) {
1352
1356
  const [open, setOpen] = useState(false);
1357
+ const portalContainer = usePortalContainer();
1353
1358
 
1354
1359
  // Drafted selection — initialized from props each time the menu opens.
1355
1360
  const [draftSort, setDraftSort] = useState<SortDirection>(sort);
@@ -1412,7 +1417,7 @@ export function DateFilterMenu({
1412
1417
  )}
1413
1418
  </Popover.Trigger>
1414
1419
 
1415
- <Popover.Portal>
1420
+ <Popover.Portal container={portalContainer ?? undefined}>
1416
1421
  <Popover.Content
1417
1422
  className={cn(
1418
1423
  'z-[9999] w-80 max-w-[calc(100vw-2rem)]',
@@ -13,7 +13,10 @@ const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
13
13
 
14
14
  const DropdownMenuGroup = DropdownMenuPrimitive.Group;
15
15
 
16
- const DropdownMenuPortal = DropdownMenuPrimitive.Portal;
16
+ function DropdownMenuPortal({ container, ...props }: ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Portal>) {
17
+ const active = usePortalContainer();
18
+ return <DropdownMenuPrimitive.Portal container={container ?? active ?? undefined} {...props} />;
19
+ }
17
20
 
18
21
  const DropdownMenuSub = DropdownMenuPrimitive.Sub;
19
22
 
@@ -5,12 +5,16 @@ import { Check, ChevronRight, Circle } from 'lucide-react';
5
5
  import { type ComponentPropsWithoutRef, type ElementRef, type HTMLAttributes, forwardRef } from 'react';
6
6
 
7
7
  import { cn } from '../../utils/cn';
8
+ import { usePortalContainer } from './portal-container';
8
9
 
9
10
  const MenubarMenu = MenubarPrimitive.Menu;
10
11
 
11
12
  const MenubarGroup = MenubarPrimitive.Group;
12
13
 
13
- const MenubarPortal = MenubarPrimitive.Portal;
14
+ function MenubarPortal({ container, ...props }: ComponentPropsWithoutRef<typeof MenubarPrimitive.Portal>) {
15
+ const active = usePortalContainer();
16
+ return <MenubarPrimitive.Portal container={container ?? active ?? undefined} {...props} />;
17
+ }
14
18
 
15
19
  const MenubarSub = MenubarPrimitive.Sub;
16
20
 
@@ -82,21 +86,24 @@ MenubarSubContent.displayName = MenubarPrimitive.SubContent.displayName;
82
86
  const MenubarContent = forwardRef<
83
87
  ElementRef<typeof MenubarPrimitive.Content>,
84
88
  ComponentPropsWithoutRef<typeof MenubarPrimitive.Content>
85
- >(({ className, align = 'start', alignOffset = -4, sideOffset = 8, ...props }, ref) => (
86
- <MenubarPrimitive.Portal>
87
- <MenubarPrimitive.Content
88
- ref={ref}
89
- align={align}
90
- alignOffset={alignOffset}
91
- sideOffset={sideOffset}
92
- className={cn(
93
- 'z-50 min-w-[12rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
94
- className,
95
- )}
96
- {...props}
97
- />
98
- </MenubarPrimitive.Portal>
99
- ));
89
+ >(({ className, align = 'start', alignOffset = -4, sideOffset = 8, ...props }, ref) => {
90
+ const container = usePortalContainer();
91
+ return (
92
+ <MenubarPrimitive.Portal container={container ?? undefined}>
93
+ <MenubarPrimitive.Content
94
+ ref={ref}
95
+ align={align}
96
+ alignOffset={alignOffset}
97
+ sideOffset={sideOffset}
98
+ className={cn(
99
+ 'z-50 min-w-[12rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
100
+ className,
101
+ )}
102
+ {...props}
103
+ />
104
+ </MenubarPrimitive.Portal>
105
+ );
106
+ });
100
107
  MenubarContent.displayName = MenubarPrimitive.Content.displayName;
101
108
 
102
109
  const MenubarItem = forwardRef<
@@ -5,6 +5,7 @@ import { RemoveScroll } from 'react-remove-scroll';
5
5
  import { ViewportBreakpoints } from '../../hooks/ui/use-content-breakpoint';
6
6
  import { cn } from '../../utils/cn';
7
7
  import { XmarkIcon } from '../icons-v2-generated';
8
+ import { CollisionBoundaryContext, PortalContainerContext } from './portal-container';
8
9
 
9
10
  // Duration of the open/close animation in ms — keep in sync with the
10
11
  // `duration-200` utilities applied to the backdrop and panel below.
@@ -66,8 +67,9 @@ interface ModalTwoColumnProps {
66
67
  // TOP one may contain focus, or they fight each other.
67
68
  const modalStack: symbol[] = [];
68
69
 
69
- // Radix popups (Select/DropdownMenu/Popover content) PORTAL to <body>, so a
70
- // dropdown opened from inside the modal focuses nodes OUTSIDE the panel.
70
+ // Radix popups (Select/DropdownMenu/Popover content) PORTAL out of the panel —
71
+ // to <body> or the modal's own portal host — so a dropdown opened from inside
72
+ // the modal focuses nodes OUTSIDE the panel.
71
73
  // Focus landing there is NOT an escape — yanking it back (containFocus /
72
74
  // reasserts / Tab trap) fights Radix's own item-focus management and strands
73
75
  // stale `data-highlighted` on items it never got to blur-clean (observed:
@@ -82,6 +84,7 @@ const Modal = forwardRef<HTMLDivElement, ModalProps>(
82
84
  ({ isOpen, onClose, children, className, size = 'default' }, ref) => {
83
85
  // Keep the modal mounted while the exit animation plays.
84
86
  const [isMounted, setIsMounted] = useState(isOpen);
87
+ const [portalHost, setPortalHost] = useState<HTMLDivElement | null>(null);
85
88
  const panelRef = useRef<HTMLDivElement | null>(null);
86
89
  const restoreFocusRef = useRef<HTMLElement | null>(null);
87
90
  const stackIdRef = useRef<symbol>(Symbol('modal'));
@@ -307,9 +310,20 @@ const Modal = forwardRef<HTMLDivElement, ModalProps>(
307
310
  aria-modal="true"
308
311
  >
309
312
  <ModalContext.Provider value={{ onClose }}>
310
- <ViewportBreakpoints>{children}</ViewportBreakpoints>
313
+ {/* Menus and tooltips opened inside portal into this layer, so they
314
+ stack over the panel instead of under the `z-[1300]` overlay. The
315
+ boundary resets too: a modal follows the window, not the surface
316
+ it was opened from. */}
317
+ <PortalContainerContext.Provider value={portalHost}>
318
+ <CollisionBoundaryContext.Provider value={null}>
319
+ <ViewportBreakpoints>{children}</ViewportBreakpoints>
320
+ </CollisionBoundaryContext.Provider>
321
+ </PortalContainerContext.Provider>
311
322
  </ModalContext.Provider>
312
323
  </div>
324
+ {/* Outside the panel: its open/close zoom is a transform, which would
325
+ anchor the menus' `position: fixed` to the panel. */}
326
+ <div ref={setPortalHost} className="contents" />
313
327
  </div>
314
328
  </RemoveScroll>
315
329
  );
@@ -8,6 +8,7 @@ import { CheckIcon, SearchIcon } from '../icons-v2-generated';
8
8
  import { Chevron02DownIcon } from '../icons-v2-generated/arrows/chevron-02-down-icon';
9
9
  import { FieldWrapper } from './field-wrapper';
10
10
  import { Input } from './input';
11
+ import { usePortalContainer } from './portal-container';
11
12
 
12
13
  export interface SearchableSelectOption {
13
14
  value: string;
@@ -112,6 +113,7 @@ export function SearchableSelect(allProps: SearchableSelectProps) {
112
113
  const [isOpen, setIsOpen] = useState(false);
113
114
  const [search, setSearch] = useState('');
114
115
  const keyboardPadding = useKeyboardCollisionPadding();
116
+ const portalContainer = usePortalContainer();
115
117
 
116
118
  // Clear the query on close, while rendering rather than from an effect: the
117
119
  // popover closes and reopens without unmounting, so an effect left the
@@ -189,7 +191,7 @@ export function SearchableSelect(allProps: SearchableSelectProps) {
189
191
  ) : (
190
192
  triggerElement
191
193
  )}
192
- <PopoverPrimitive.Portal>
194
+ <PopoverPrimitive.Portal container={portalContainer ?? undefined}>
193
195
  <PopoverPrimitive.Content
194
196
  align={align}
195
197
  sideOffset={6}
@@ -7,6 +7,7 @@ import { cn } from '../../utils/cn';
7
7
  import { Chevron02DownIcon } from '../icons-v2-generated/arrows/chevron-02-down-icon';
8
8
  import { CheckIcon } from '../icons-v2-generated/signs-and-symbols/check-icon';
9
9
  import { FieldWrapper } from './field-wrapper';
10
+ import { usePortalContainer } from './portal-container';
10
11
 
11
12
  const Select = SelectPrimitive.Root;
12
13
 
@@ -114,30 +115,33 @@ SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayNam
114
115
  const SelectContent = forwardRef<
115
116
  ComponentRef<typeof SelectPrimitive.Content>,
116
117
  ComponentPropsWithoutRef<typeof SelectPrimitive.Content>
117
- >(({ className, children, position = 'popper', ...props }, ref) => (
118
- <SelectPrimitive.Portal>
119
- <SelectPrimitive.Content
120
- ref={ref}
121
- className={cn(
122
- 'relative z-[9999] max-h-96 overflow-hidden rounded-[4px] border border-ods-border bg-ods-card text-ods-text-primary',
123
- 'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
124
- position === 'popper' &&
125
- 'data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1',
126
- className,
127
- )}
128
- position={position}
129
- style={{
130
- width: 'var(--radix-select-trigger-width)',
131
- minWidth: 'var(--radix-select-trigger-width)',
132
- }}
133
- {...props}
134
- >
135
- <SelectScrollUpButton />
136
- <SelectPrimitive.Viewport className="w-full">{children}</SelectPrimitive.Viewport>
137
- <SelectScrollDownButton />
138
- </SelectPrimitive.Content>
139
- </SelectPrimitive.Portal>
140
- ));
118
+ >(({ className, children, position = 'popper', ...props }, ref) => {
119
+ const container = usePortalContainer();
120
+ return (
121
+ <SelectPrimitive.Portal container={container ?? undefined}>
122
+ <SelectPrimitive.Content
123
+ ref={ref}
124
+ className={cn(
125
+ 'relative z-[9999] max-h-96 overflow-hidden rounded-[4px] border border-ods-border bg-ods-card text-ods-text-primary',
126
+ 'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
127
+ position === 'popper' &&
128
+ 'data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1',
129
+ className,
130
+ )}
131
+ position={position}
132
+ style={{
133
+ width: 'var(--radix-select-trigger-width)',
134
+ minWidth: 'var(--radix-select-trigger-width)',
135
+ }}
136
+ {...props}
137
+ >
138
+ <SelectScrollUpButton />
139
+ <SelectPrimitive.Viewport className="w-full">{children}</SelectPrimitive.Viewport>
140
+ <SelectScrollDownButton />
141
+ </SelectPrimitive.Content>
142
+ </SelectPrimitive.Portal>
143
+ );
144
+ });
141
145
  SelectContent.displayName = SelectPrimitive.Content.displayName;
142
146
 
143
147
  const SelectLabel = forwardRef<
@@ -7,6 +7,7 @@ import { cn } from '../../utils/cn';
7
7
  import { CheckIcon, PlusIcon, SearchIcon, TrashIcon } from '../icons-v2-generated';
8
8
  import { Button } from './button';
9
9
  import { Input } from './input';
10
+ import { usePortalContainer } from './portal-container';
10
11
 
11
12
  export interface TagSelectOption {
12
13
  id: string;
@@ -61,6 +62,7 @@ export function TagSelectDropdown({
61
62
  const [isOpen, setIsOpen] = useState(false);
62
63
  const [search, setSearch] = useState('');
63
64
  const keyboardPadding = useKeyboardCollisionPadding();
65
+ const portalContainer = usePortalContainer();
64
66
 
65
67
  // Clear the query on close, while rendering rather than from an effect: the
66
68
  // popover closes and reopens without unmounting, so an effect left the
@@ -110,7 +112,7 @@ export function TagSelectDropdown({
110
112
  {triggerLabel}
111
113
  </Button>
112
114
  </PopoverPrimitive.Trigger>
113
- <PopoverPrimitive.Portal>
115
+ <PopoverPrimitive.Portal container={portalContainer ?? undefined}>
114
116
  <PopoverPrimitive.Content
115
117
  align={align}
116
118
  sideOffset={6}