Skip to content

Commit 9ff7bec

Browse files
authored
Merge pull request #1 from jsmbennett/claude/fix-contextmenu-animation-Sa2ed
Simplify context menu positioning logic
2 parents 2ac0021 + 8644cb6 commit 9ff7bec

1 file changed

Lines changed: 28 additions & 32 deletions

File tree

src/components/contextmenu.js

Lines changed: 28 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@ import win98Styles from '../css/98-overrides.css?inline';
33
/**
44
* @element win98-context-menu
55
* @description A Windows 98-style context menu that appears on right-click
6-
*
7-
* The menu animates diagonally away from the closest corner of the viewport.
6+
*
7+
* The menu animates towards the bottom-right by default, or bottom-left if there
8+
* is insufficient space on the right side of the screen.
89
*
910
* @attr {boolean} visible - Controls whether the menu is displayed
1011
*
@@ -191,25 +192,26 @@ class Win98ContextMenu extends HTMLElement {
191192
this.closeAllSubmenus();
192193
this.classList.remove('animation-done');
193194

194-
// Determine the closest corner and animation direction
195-
const direction = this._calculateDirection(x, y);
196-
this.setAttribute('data-direction', direction);
197-
198195
// Show menu first to measure it
199196
this.setAttribute('visible', '');
200-
197+
201198
// Handle animation end to remove clip-path for nested submenus
202199
const menu = this.shadowRoot.querySelector('.context-menu');
203-
if (menu) {
204-
const onAnimationEnd = () => {
205-
this.classList.add('animation-done');
206-
menu.removeEventListener('animationend', onAnimationEnd);
207-
};
208-
menu.addEventListener('animationend', onAnimationEnd);
209-
}
210-
211-
// Position the menu so the appropriate corner is at the cursor
200+
201+
// Determine animation direction after menu is visible so we can measure it
212202
requestAnimationFrame(() => {
203+
const direction = this._calculateDirection(x, y, menu);
204+
this.setAttribute('data-direction', direction);
205+
206+
if (menu) {
207+
const onAnimationEnd = () => {
208+
this.classList.add('animation-done');
209+
menu.removeEventListener('animationend', onAnimationEnd);
210+
};
211+
menu.addEventListener('animationend', onAnimationEnd);
212+
}
213+
214+
// Position the menu so the appropriate corner is at the cursor
213215
this._positionAtCursor(x, y, direction);
214216
});
215217
}
@@ -289,30 +291,24 @@ class Win98ContextMenu extends HTMLElement {
289291
}
290292

291293
/**
292-
* Calculate which direction to animate based on closest viewport corner
294+
* Calculate which direction to animate based on available space
293295
* @param {number} x - Click X position
294296
* @param {number} y - Click Y position
295-
* @returns {string} Direction: 'top-left', 'top-right', 'bottom-left', 'bottom-right'
297+
* @param {HTMLElement} menu - The menu element to measure
298+
* @returns {string} Direction: 'bottom-right' or 'bottom-left'
296299
*/
297-
_calculateDirection(x, y) {
300+
_calculateDirection(x, y, menu) {
298301
const viewportWidth = window.innerWidth;
299-
const viewportHeight = window.innerHeight;
302+
const menuWidth = menu ? menu.getBoundingClientRect().width : 0;
300303

301-
// Determine which half of the screen we're in
302-
const isLeft = x < viewportWidth / 2;
303-
const isTop = y < viewportHeight / 2;
304+
// Default to bottom-right, but use bottom-left if there's not enough space on the right
305+
const spaceOnRight = viewportWidth - x;
304306

305-
// Animation direction is AWAY from the closest corner
306-
// If click is in top-left quadrant, closest corner is top-left, animate toward bottom-right
307-
if (isTop && isLeft) {
308-
return 'bottom-right';
309-
} else if (isTop && !isLeft) {
307+
if (spaceOnRight < menuWidth) {
310308
return 'bottom-left';
311-
} else if (!isTop && isLeft) {
312-
return 'top-right';
313-
} else {
314-
return 'top-left';
315309
}
310+
311+
return 'bottom-right';
316312
}
317313

318314
/**

0 commit comments

Comments
 (0)