11/* eslint-disable react-hooks/rules-of-hooks */
22
3- import React , { useState } from 'react' ;
3+ import React , { useRef , useState } from 'react' ;
44import {
55 storybookArgTypes ,
66 storybookExcludedControlParams ,
77 type StoryMetaType ,
88} from '@lg-tools/storybook-utils' ;
99import { StoryObj } from '@storybook/react' ;
10- import { userEvent , within } from '@storybook/test' ;
10+ import { fn , userEvent , within } from '@storybook/test' ;
1111
1212import Button from '@leafygreen-ui/button' ;
13- import { css } from '@leafygreen-ui/emotion' ;
13+ import { css , cx } from '@leafygreen-ui/emotion' ;
1414import Icon from '@leafygreen-ui/icon' ;
1515import CaretDown from '@leafygreen-ui/icon/dist/CaretDown' ;
1616import CloudIcon from '@leafygreen-ui/icon/dist/Cloud' ;
@@ -20,6 +20,8 @@ import { TestUtils } from '@leafygreen-ui/popover';
2020
2121const { getAlign, getJustify } = TestUtils ;
2222
23+ import { useEventListener } from '@leafygreen-ui/hooks' ;
24+
2325import {
2426 Menu ,
2527 MenuGroup ,
@@ -100,6 +102,7 @@ const meta: StoryMetaType<typeof Menu> = {
100102 darkMode : false ,
101103 renderDarkMenu : false ,
102104 variant : MenuVariant . Default ,
105+ onOpen : fn ( ) ,
103106 } ,
104107 argTypes : {
105108 open : {
@@ -476,3 +479,89 @@ export const InitialLongMenuOpen: InitialLongMenuOpenStory = {
476479 ) ,
477480 ] ,
478481} ;
482+
483+ export const MovingMenuTrigger = ( ) => {
484+ const markerStyles = css `
485+ position : absolute;
486+ color : black;
487+ text-align : center;
488+ outline : 1px solid black;
489+ cursor : default;
490+ ` ;
491+
492+ const [ open , setOpen ] = useState ( false ) ;
493+ const [ position , setPosition ] = useState ( { top : 0 , left : 0 } ) ;
494+ const anchorRef = useRef < HTMLDivElement > ( null ) ;
495+ useEventListener (
496+ 'contextmenu' ,
497+ event => {
498+ event . preventDefault ( ) ;
499+ const { clientX, clientY } = event ;
500+ setOpen ( true ) ;
501+ setPosition ( { top : clientY , left : clientX } ) ;
502+ } ,
503+ { dependencies : [ setPosition , setOpen ] } ,
504+ ) ;
505+ useEventListener (
506+ 'click' ,
507+ event => {
508+ event . preventDefault ( ) ;
509+ if ( event . buttons === 2 ) return ;
510+ setOpen ( false ) ;
511+ } ,
512+ { dependencies : [ setOpen ] } ,
513+ ) ;
514+
515+ return (
516+ < div className = "App" >
517+ < div
518+ ref = { anchorRef }
519+ style = { { position : 'absolute' , width : 1 , height : 1 , ...position } }
520+ />
521+ < div
522+ className = { cx (
523+ markerStyles ,
524+ css `
525+ top : 40vh ;
526+ left : 50vw ;
527+ ` ,
528+ ) }
529+ >
530+ Click here for a shorter menu
531+ </ div >
532+ < div
533+ className = { cx (
534+ markerStyles ,
535+ css `
536+ top : 10vh ;
537+ left : 50vw ;
538+ ` ,
539+ ) }
540+ >
541+ Click here for a long menu
542+ </ div >
543+ < Menu refEl = { anchorRef } open = { open } maxHeight = { Number . MAX_SAFE_INTEGER } >
544+ < MenuItem > Item #1</ MenuItem >
545+ < MenuItem > Item #2</ MenuItem >
546+ < MenuItem > Item #3</ MenuItem >
547+ < MenuItem > Item #4</ MenuItem >
548+ < MenuItem > Item #5</ MenuItem >
549+ < MenuItem > Item #6</ MenuItem >
550+ < MenuItem > Item #7</ MenuItem >
551+ < MenuItem > Item #8</ MenuItem >
552+ < MenuItem > Item #9</ MenuItem >
553+ < MenuItem > Item #10</ MenuItem >
554+ < MenuItem > Item #11</ MenuItem >
555+ < MenuItem > Item #12</ MenuItem >
556+ < MenuItem > Item #13</ MenuItem >
557+ < MenuItem > Item #14</ MenuItem >
558+ < MenuItem > Item #15</ MenuItem >
559+ < MenuItem > Item #16</ MenuItem >
560+ < MenuItem > Item #17</ MenuItem >
561+ < MenuItem > Item #18</ MenuItem >
562+ < MenuItem > Item #19</ MenuItem >
563+ < MenuItem > Item #20</ MenuItem >
564+ </ Menu >
565+ </ div >
566+ ) ;
567+ } ;
0 commit comments