From 3237d5953f1f0a0e4d0b3821fe2e7c4c29e0fb20 Mon Sep 17 00:00:00 2001 From: ajnart Date: Sun, 16 Aug 2026 14:15:14 +0200 Subject: [PATCH] fix(board): render widget options above grid resize handles The widget options ActionIcon rendered inside the widget Card, whose containerType: size creates a stacking context, trapping its zIndex and letting the dnd-kit resize handles paint over and block it. Hoist BoardItemMenu out of the Card to the item root (same layer as the title badge) and raise it to zIndex 30, above the handles (20). Error recovery after edits is preserved via resetKeys=[item], which replaces the resetErrorBoundary prop the in-card menu used to receive. --- .../components/board/items/item-content.tsx | 51 +++++++++---------- .../src/components/board/items/item-menu.tsx | 2 +- 2 files changed, 24 insertions(+), 29 deletions(-) diff --git a/apps/nextjs/src/components/board/items/item-content.tsx b/apps/nextjs/src/components/board/items/item-content.tsx index 5cfd613dc..d8505a0c7 100644 --- a/apps/nextjs/src/components/board/items/item-content.tsx +++ b/apps/nextjs/src/components/board/items/item-content.tsx @@ -1,5 +1,5 @@ import type { ComponentType, CSSProperties, MutableRefObject } from "react"; -import { memo, Suspense, use, useCallback, useEffect, useRef, useState } from "react"; +import { memo, Suspense, use, useCallback, useEffect, useMemo, useRef, useState } from "react"; import { createPortal } from "react-dom"; import dynamic from "next/dynamic"; import type { CardProps } from "@mantine/core"; @@ -159,6 +159,11 @@ const LoadedBoardItemContent = ({ const board = useRequiredBoard(); const t = useI18n(); const [isEditMode] = useEditMode(); + const settings = useSettings(); + const menuItem = useMemo( + () => ({ ...item, options: reduceWidgetOptionsWithDefinition(definition, settings, item.options) }), + [definition, item, settings], + ); const [manualSurface, setManualSurface] = useState(null); const [surfacePortalTarget, setSurfacePortalTarget] = useState(null); const { active, viewportSize, open, close, dismiss, hover, leave } = useAdvancedFocus(); @@ -305,20 +310,15 @@ const LoadedBoardItemContent = ({ > ( - <> - {isEditMode && ( - - )} -
- -
- +
+ +
)} > + {isEditMode && } }) => updateItemOptions({ itemId: item.id, newOptions }); @@ -462,19 +462,15 @@ const InnerContent = memo(function InnerContent({ item, definition, Component, . removeWidgetDataQueries(queryClient, widgetQueryKeys); reset(); }} + resetKeys={[item]} fallbackRender={({ resetErrorBoundary, error }) => ( - <> - {isEditMode && ( - - )} -
- -
- +
+ +
)} > - {isEditMode && }