@@ -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