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 closeMenu = () => setScaleMenuPos(null);
const origin = scaleMenuOriginRef.current || scaleMenuPos;
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 pushItem = (label, onClick, indent, onHover) => {
const pushItem = (label, onClick, onHover) => {
const isActive = onClick._scale && isSameScale(onClick._scale, selectedScale);
items.push(React.createElement("div", {
key: label,
onClick: () => { onClick(); closeMenu(); },
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));
};
Object.keys(SCALES).forEach(key => {
@@ -5527,21 +5529,32 @@ const PianoRollTabEditor = ({ st, zoom, bpm, viewportWidth, onClose, onUpdateNot
} else {
const parentKey = key;
const isOpen = scaleMenuPos && scaleMenuPos.parentKey === parentKey;
pushItem(key + " ▸", () => setSelectedScale(null), false, () => {
const origin = scaleMenuOriginRef.current || scaleMenuPos;
setScaleMenuPos({ x: origin.x + 140, y: origin.y, parentKey });
pushItem(key + " ▸", () => setSelectedScale(null), () => {
setScaleMenuPos({ x: origin.x, y: origin.y, parentKey });
});
if (isOpen) {
const subItems = [];
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", {
style: { position: "fixed", left: scaleMenuPos.x, top: scaleMenuPos.y, zIndex: 9999 },
className: "bg-[#2a2a2a] border border-zinc-600 rounded shadow-xl py-1 min-w-[140px]"
}, ...items);
return React.createElement(React.Fragment, null,
React.createElement("div", {
style: { position: "fixed", left: origin.x, top: origin.y, zIndex: 9999 },
className: "bg-[#2a2a2a] border border-zinc-600 rounded shadow-xl py-1 min-w-[140px]"
}, ...items),
subMenu
);
};
const renderBarLabels = () => {
File diff suppressed because one or more lines are too long