fix: scale sub-menu as separate floating panel, not shifted main menu

Sub-menu items now render as a standalone fixed-position panel
at origin.x+150, not mixed into the main menu. Main menu stays
at its initial position. Hover to open, click to select scale.
This commit is contained in:
2026-07-25 12:22:18 +07:00
parent 5497bd1256
commit 66cb05f26c
2 changed files with 24 additions and 11 deletions
+23 -10
View File
@@ -5508,15 +5508,17 @@ const PianoRollTabEditor = ({ st, zoom, bpm, viewportWidth, onClose, onUpdateNot
const renderScaleContextMenu = () => { const renderScaleContextMenu = () => {
const closeMenu = () => setScaleMenuPos(null); const closeMenu = () => setScaleMenuPos(null);
const origin = scaleMenuOriginRef.current || scaleMenuPos;
const items = []; const items = [];
let subMenu = null;
const isSameScale = (a, b) => { if (!a || !b) return a === b; if (a.length !== b.length) return false; return a.every((v,i)=>v===b[i]); }; const isSameScale = (a, b) => { if (!a || !b) return a === b; if (a.length !== b.length) return false; return a.every((v,i)=>v===b[i]); };
const pushItem = (label, onClick, indent, onHover) => { const pushItem = (label, onClick, onHover) => {
const isActive = onClick._scale && isSameScale(onClick._scale, selectedScale); const isActive = onClick._scale && isSameScale(onClick._scale, selectedScale);
items.push(React.createElement("div", { items.push(React.createElement("div", {
key: label, key: label,
onClick: () => { onClick(); closeMenu(); }, onClick: () => { onClick(); closeMenu(); },
onMouseEnter: onHover || undefined, onMouseEnter: onHover || undefined,
className: "px-3 py-1.5 text-xs cursor-pointer hover:bg-amber-600 hover:text-white whitespace-nowrap " + (indent ? "pl-6 " : "") + (isActive ? "bg-amber-800/40 text-amber-300" : "text-zinc-300") className: "px-3 py-1.5 text-xs cursor-pointer hover:bg-amber-600 hover:text-white whitespace-nowrap " + (isActive ? "bg-amber-800/40 text-amber-300" : "text-zinc-300")
}, label)); }, label));
}; };
Object.keys(SCALES).forEach(key => { Object.keys(SCALES).forEach(key => {
@@ -5527,21 +5529,32 @@ const PianoRollTabEditor = ({ st, zoom, bpm, viewportWidth, onClose, onUpdateNot
} else { } else {
const parentKey = key; const parentKey = key;
const isOpen = scaleMenuPos && scaleMenuPos.parentKey === parentKey; const isOpen = scaleMenuPos && scaleMenuPos.parentKey === parentKey;
pushItem(key + " ▸", () => setSelectedScale(null), false, () => { pushItem(key + " ▸", () => setSelectedScale(null), () => {
const origin = scaleMenuOriginRef.current || scaleMenuPos; setScaleMenuPos({ x: origin.x, y: origin.y, parentKey });
setScaleMenuPos({ x: origin.x + 140, y: origin.y, parentKey });
}); });
if (isOpen) { if (isOpen) {
const subItems = [];
Object.keys(val).forEach(subKey => { Object.keys(val).forEach(subKey => {
pushItem(subKey, () => setSelectedScale(val[subKey]), true); subItems.push(React.createElement("div", {
key: subKey,
onClick: () => { setSelectedScale(val[subKey]); closeMenu(); },
className: "px-3 py-1.5 text-xs cursor-pointer hover:bg-amber-600 hover:text-white whitespace-nowrap " + (isSameScale(val[subKey], selectedScale) ? "bg-amber-800/40 text-amber-300" : "text-zinc-300")
}, subKey));
}); });
subMenu = React.createElement("div", {
style: { position: "fixed", left: origin.x + 150, top: origin.y, zIndex: 10000 },
className: "bg-[#2a2a2a] border border-zinc-600 rounded shadow-xl py-1 min-w-[120px]"
}, ...subItems);
} }
} }
}); });
return React.createElement("div", { return React.createElement(React.Fragment, null,
style: { position: "fixed", left: scaleMenuPos.x, top: scaleMenuPos.y, zIndex: 9999 }, React.createElement("div", {
className: "bg-[#2a2a2a] border border-zinc-600 rounded shadow-xl py-1 min-w-[140px]" style: { position: "fixed", left: origin.x, top: origin.y, zIndex: 9999 },
}, ...items); className: "bg-[#2a2a2a] border border-zinc-600 rounded shadow-xl py-1 min-w-[140px]"
}, ...items),
subMenu
);
}; };
const renderBarLabels = () => { const renderBarLabels = () => {
File diff suppressed because one or more lines are too long