The space and section context menus repeated the same dropdown with an invisible trigger anchored at the pointer; only their label and items differ. Move-only: PointerMenu in pages/shell renders that dropdown and both menus pass their label, close handler and items. DOM, attributes and handlers are unchanged, and the labels stay in ShellPage, so the catalogs do not change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MRtGG9ARfqqhma3t85Ro2u
42 lines
1.1 KiB
TypeScript
42 lines
1.1 KiB
TypeScript
import { DropdownMenu, DropdownMenuContent, DropdownMenuTrigger } from "@rakazo/ui-web";
|
|
import type { ReactNode } from "react";
|
|
import type { ContextMenuPosition } from "../BotContextMenu";
|
|
|
|
/** A dropdown menu opened at the pointer, for sidebar context menus. */
|
|
export function PointerMenu({
|
|
position,
|
|
label,
|
|
onClose,
|
|
children,
|
|
}: {
|
|
position: ContextMenuPosition;
|
|
label: string;
|
|
onClose: () => void;
|
|
children: ReactNode;
|
|
}) {
|
|
return (
|
|
<DropdownMenu
|
|
open
|
|
onOpenChange={(open) => {
|
|
if (!open) onClose();
|
|
}}
|
|
>
|
|
{/* Invisible anchor at the pointer position, mirroring the bot menu. */}
|
|
<DropdownMenuTrigger
|
|
render={
|
|
<button
|
|
type="button"
|
|
tabIndex={-1}
|
|
aria-hidden
|
|
className="fixed size-0 p-0 opacity-0"
|
|
style={{ left: position.x, top: position.y }}
|
|
/>
|
|
}
|
|
/>
|
|
<DropdownMenuContent aria-label={label} align="start" sideOffset={0} className="w-[220px]">
|
|
{children}
|
|
</DropdownMenuContent>
|
|
</DropdownMenu>
|
|
);
|
|
}
|