@@ -68,6 +68,16 @@ export const DropdownMenuHandlerContext = createContext<DropdownMenuHandler>(
6868 { }
6969) ;
7070
71+ type OpenSubmenuContext = {
72+ openSubmenuKeys : { [ key : string ] : { isOpen : boolean ; level : number } } ;
73+ handleSubmenuOpen : ( key : string , level : number ) => void ;
74+ } ;
75+
76+ export const OpenSubmenuContext = createContext < OpenSubmenuContext > ( {
77+ openSubmenuKeys : { } ,
78+ handleSubmenuOpen : ( ) => { } ,
79+ } ) ;
80+
7181/**
7282 *
7383 */
@@ -82,6 +92,8 @@ export type DropdownMenuItemProps = {
8292 onClick ?: ( e : React . SyntheticEvent ) => void ;
8393 submenu ?: ReactNode ;
8494 submenuItems ?: Array < { key : string | number } & DropdownMenuItemProps > ;
95+ openSubmenuKey ?: string | number ;
96+ level ?: number ;
8597} & Omit < AnchorHTMLAttributes < HTMLAnchorElement > , 'onClick' > ;
8698
8799/**
@@ -104,13 +116,16 @@ export const DropdownMenuItem: FC<DropdownMenuItemProps> = (props) => {
104116 submenu : submenu_ ,
105117 submenuItems,
106118 children,
119+ level = 0 ,
107120 ...rprops
108121 } = props ;
109122
110123 const { onMenuSelect, onMenuBlur, onMenuFocus } = useContext (
111124 DropdownMenuHandlerContext
112125 ) ;
113126
127+ const { openSubmenuKeys, handleSubmenuOpen } = useContext ( OpenSubmenuContext ) ;
128+
114129 const onKeyDown = useEventCallback ( ( e : KeyboardEvent < HTMLAnchorElement > ) => {
115130 if ( e . keyCode === 13 || e . keyCode === 32 ) {
116131 // return or space
@@ -162,8 +177,8 @@ export const DropdownMenuItem: FC<DropdownMenuItemProps> = (props) => {
162177
163178 const onMenuItemClick = useEventCallback (
164179 ( e : SyntheticEvent < HTMLAnchorElement > ) => {
165- if ( submenu ) {
166- setSubmenuExpanded ( ( expanded ) => ! expanded ) ;
180+ if ( submenu && eventKey !== undefined ) {
181+ handleSubmenuOpen ( eventKey . toString ( ) , level + 1 ) ;
167182 return ;
168183 }
169184 onClick ?.( e ) ;
@@ -192,11 +207,13 @@ export const DropdownMenuItem: FC<DropdownMenuItemProps> = (props) => {
192207 ( submenuItems ? (
193208 < DropdownSubmenu label = { label } >
194209 { submenuItems ?. map ( ( { key, ...itemProps } ) => (
195- < DropdownMenuItem key = { key } { ...itemProps } />
210+ < DropdownMenuItem key = { key } level = { level + 1 } { ...itemProps } />
196211 ) ) }
197212 </ DropdownSubmenu >
198213 ) : undefined ) ;
199- const [ submenuExpanded , setSubmenuExpanded ] = useState ( false ) ;
214+
215+ const submenuExpanded =
216+ eventKey !== undefined ? openSubmenuKeys [ eventKey ] ?. isOpen ?? false : false ;
200217
201218 const menuItemClass = classnames (
202219 'slds-dropdown__item' ,
@@ -340,6 +357,27 @@ const DropdownMenuInner: FC<DropdownMenuProps & AutoAlignInjectedProps> = (
340357 } ) ,
341358 [ onBlur , onFocus , onMenuSelect ]
342359 ) ;
360+
361+ const [ openSubmenuKeys , setOpenSubmenuKeys ] = useState < {
362+ [ key : string ] : { isOpen : boolean ; level : number } ;
363+ } > ( { } ) ;
364+
365+ const handleSubmenuOpen = ( key : string , level : number ) => {
366+ setOpenSubmenuKeys ( ( prevState ) => {
367+ const newState = { ...prevState } ;
368+ Object . keys ( newState ) . forEach ( ( submenuKey ) => {
369+ // メニューをクリックしてサブメニューを開く、サブメニューをクリックするとそのサブメニューを開く
370+ // 開いているメニューをクリックした場合、そのメニューとサブメニューを閉じる
371+ // 同じレベルのメニューをクリックした場合、それ以外の同じレベルのメニューとそのサブメニューを閉じる
372+ if ( newState [ submenuKey ] . level >= level && key !== submenuKey ) {
373+ newState [ submenuKey ] . isOpen = false ;
374+ }
375+ } ) ;
376+ newState [ key ] = { isOpen : ! newState [ key ] ?. isOpen , level } ;
377+ return newState ;
378+ } ) ;
379+ } ;
380+
343381 return (
344382 < div
345383 className = { dropdownClassNames }
@@ -354,7 +392,11 @@ const DropdownMenuInner: FC<DropdownMenuProps & AutoAlignInjectedProps> = (
354392 { header ? < MenuHeader > { header } </ MenuHeader > : null }
355393 < ul className = 'slds-dropdown__list' role = 'menu' >
356394 < DropdownMenuHandlerContext . Provider value = { handlers } >
357- { children }
395+ < OpenSubmenuContext . Provider
396+ value = { { openSubmenuKeys, handleSubmenuOpen } }
397+ >
398+ { children }
399+ </ OpenSubmenuContext . Provider >
358400 </ DropdownMenuHandlerContext . Provider >
359401 </ ul >
360402 </ div >
0 commit comments