From 19b3dc658a56ad50d1e3e8a6ddce8bedc5147f84 Mon Sep 17 00:00:00 2001 From: zsviczian Date: Wed, 22 Oct 2025 23:29:39 +0200 Subject: [PATCH] fix: set radix PropertiesPopover collision boundary (#10221) * Set collision boundary * Calculate collisionPadding dynamically based on container * Add appState offsetTop and offsetLeft to padding calculation. Refactor collisionPadding calculation to use app state offsets. * Update PropertiesPopover.tsx * popover positioning relative to container --- packages/excalidraw/components/IconPicker.tsx | 4 +++- .../excalidraw/components/PropertiesPopover.tsx | 15 +++++---------- packages/excalidraw/components/ToolPopover.tsx | 4 ++++ 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/packages/excalidraw/components/IconPicker.tsx b/packages/excalidraw/components/IconPicker.tsx index 031d181eb0..13c69cf8fd 100644 --- a/packages/excalidraw/components/IconPicker.tsx +++ b/packages/excalidraw/components/IconPicker.tsx @@ -8,7 +8,7 @@ import { atom, useAtom } from "../editor-jotai"; import { getLanguage, t } from "../i18n"; import Collapsible from "./Stats/Collapsible"; -import { useDevice } from "./App"; +import { useDevice, useExcalidrawContainer } from "./App"; import "./IconPicker.scss"; @@ -39,6 +39,7 @@ function Picker({ numberOfOptionsToAlwaysShow?: number; }) { const device = useDevice(); + const { container } = useExcalidrawContainer(); const handleKeyDown = (event: React.KeyboardEvent) => { const pressedOption = options.find( @@ -161,6 +162,7 @@ function Picker({ sideOffset={isMobile ? 8 : 12} style={{ zIndex: "var(--zIndex-ui-styles-popup)" }} onKeyDown={handleKeyDown} + collisionBoundary={container ?? undefined} >
{ const device = useDevice(); + const isMobilePortrait = + device.editor.isMobile && !device.viewport.isLandscape; return ( @@ -47,18 +49,11 @@ export const PropertiesPopover = React.forwardRef< ref={ref} className={clsx("focus-visible-none", className)} data-prevent-outside-click - side={ - device.editor.isMobile && !device.viewport.isLandscape - ? "bottom" - : "right" - } - align={ - device.editor.isMobile && !device.viewport.isLandscape - ? "center" - : "start" - } + side={isMobilePortrait ? "bottom" : "right"} + align={isMobilePortrait ? "center" : "start"} alignOffset={-16} sideOffset={20} + collisionBoundary={container ?? undefined} style={{ zIndex: "var(--zIndex-ui-styles-popup)", marginLeft: device.editor.isMobile ? "0.5rem" : undefined, diff --git a/packages/excalidraw/components/ToolPopover.tsx b/packages/excalidraw/components/ToolPopover.tsx index 81d5726d5a..b1fed1cbf1 100644 --- a/packages/excalidraw/components/ToolPopover.tsx +++ b/packages/excalidraw/components/ToolPopover.tsx @@ -11,6 +11,8 @@ import { ToolButton } from "./ToolButton"; import "./ToolPopover.scss"; +import { useExcalidrawContainer } from "./App"; + import type { AppClassProperties } from "../types"; type ToolOption = { @@ -50,6 +52,7 @@ export const ToolPopover = ({ const currentType = activeTool.type; const isActive = displayedOption.type === currentType; const SIDE_OFFSET = 32 / 2 + 10; + const { container } = useExcalidrawContainer(); // if currentType is not in options, close popup if (!options.some((o) => o.type === currentType) && isPopupOpen) { @@ -90,6 +93,7 @@ export const ToolPopover = ({ {options.map(({ type, icon, title }) => (