11import type { ReactNode , FunctionComponent } from 'react' ;
2- import { Children , isValidElement , useState } from 'react' ;
2+ import { Children , isValidElement , useState , useContext } from 'react' ;
33import { Button , Dropdown , DropdownList , MenuToggle , OverflowMenu , OverflowMenuContent , OverflowMenuControl , OverflowMenuDropdownItem , OverflowMenuGroup , OverflowMenuItem , OverflowMenuProps } from '@patternfly/react-core' ;
44import { EllipsisVIcon } from '@patternfly/react-icons' ;
55import { ResponsiveActionProps } from '../ResponsiveAction' ;
6+ import { OverflowMenuContext } from '@patternfly/react-core/dist/esm/components/OverflowMenu/OverflowMenuContext' ;
67
78/** extends OverflowMenuProps */
89export interface ResponsiveActionsProps extends Omit < OverflowMenuProps , 'ref' | 'breakpoint' > {
@@ -14,13 +15,68 @@ export interface ResponsiveActionsProps extends Omit<OverflowMenuProps, 'ref' |
1415 children : React . ReactNode ;
1516}
1617
17- export const ResponsiveActions : FunctionComponent < ResponsiveActionsProps > = ( { ouiaId = 'ResponsiveActions' , breakpoint = 'lg' , children, ...props } : ResponsiveActionsProps ) => {
18+ // Inner component that has access to OverflowMenuContext
19+ const ResponsiveActionsDropdown : FunctionComponent < {
20+ ouiaId : string ;
21+ dropdownItems : ReactNode [ ] ;
22+ pinnedItemsDisabled : boolean [ ] ;
23+ regularItemsDisabled : boolean [ ] ;
24+ } > = ( { ouiaId, dropdownItems, pinnedItemsDisabled, regularItemsDisabled } ) => {
1825 const [ isOpen , setIsOpen ] = useState ( false ) ;
26+ const { isBelowBreakpoint } = useContext ( OverflowMenuContext ) ;
27+
28+ // Determine if kebab should be disabled based on breakpoint
29+ const isKebabDisabled = ( ( ) => {
30+ const allPinnedDisabled = pinnedItemsDisabled . length > 0 && pinnedItemsDisabled . every ( disabled => disabled ) ;
31+ const allRegularDisabled = regularItemsDisabled . length > 0 && regularItemsDisabled . every ( disabled => disabled ) ;
32+
33+ if ( isBelowBreakpoint ) {
34+ // Below breakpoint: pinned items are IN the dropdown, so check all dropdown items
35+ // Disabled only if both pinned AND regular items exist and are all disabled
36+ return ( pinnedItemsDisabled . length > 0 || regularItemsDisabled . length > 0 ) &&
37+ ( pinnedItemsDisabled . length === 0 || allPinnedDisabled ) &&
38+ ( regularItemsDisabled . length === 0 || allRegularDisabled ) ;
39+ } else {
40+ // Above breakpoint: pinned items are shown as buttons, only check regular items
41+ // Disabled only if there are regular items and they're all disabled
42+ return allRegularDisabled ;
43+ }
44+ } ) ( ) ;
45+
46+ return (
47+ < Dropdown
48+ ouiaId = { `${ ouiaId } -menu-dropdown` }
49+ onSelect = { ( ) => setIsOpen ( false ) }
50+ toggle = { ( toggleRef ) => (
51+ < MenuToggle
52+ ouiaId = { `${ ouiaId } -menu-dropdown-toggle` }
53+ ref = { toggleRef }
54+ aria-label = "Actions overflow menu"
55+ variant = "plain"
56+ icon = { < EllipsisVIcon /> }
57+ onClick = { ( ) => setIsOpen ( ! isOpen ) }
58+ isExpanded = { isOpen }
59+ isDisabled = { isKebabDisabled }
60+ />
61+ ) }
62+ isOpen = { isOpen }
63+ onOpenChange = { setIsOpen }
64+ >
65+ < DropdownList data-ouia-component-id = { `${ ouiaId } -menu-dropdown-list` } >
66+ { dropdownItems }
67+ </ DropdownList >
68+ </ Dropdown >
69+ ) ;
70+ } ;
71+
72+ export const ResponsiveActions : FunctionComponent < ResponsiveActionsProps > = ( { ouiaId = 'ResponsiveActions' , breakpoint = 'lg' , children, ...props } : ResponsiveActionsProps ) => {
1973
2074 // separate persistent, pinned and collapsed actions
2175 const persistentActions : ReactNode [ ] = [ ] ;
2276 const pinnedActions : ReactNode [ ] = [ ] ;
2377 const dropdownItems : ReactNode [ ] = [ ] ;
78+ const pinnedItemsDisabled : boolean [ ] = [ ] ;
79+ const regularItemsDisabled : boolean [ ] = [ ] ;
2480 let hasRegularActions = false ;
2581
2682 Children . forEach ( children , ( child , index ) => {
@@ -47,6 +103,12 @@ export const ResponsiveActions: FunctionComponent<ResponsiveActionsProps> = ({ o
47103 { children }
48104 </ OverflowMenuDropdownItem >
49105 ) ;
106+ // Track disabled state separately for pinned vs regular items
107+ if ( isPinned ) {
108+ pinnedItemsDisabled . push ( ! ! actionProps . isDisabled ) ;
109+ } else {
110+ regularItemsDisabled . push ( ! ! actionProps . isDisabled ) ;
111+ }
50112 }
51113 }
52114 } ) ;
@@ -74,27 +136,12 @@ export const ResponsiveActions: FunctionComponent<ResponsiveActionsProps> = ({ o
74136 ) : null }
75137 { dropdownItems . length > 0 && (
76138 < OverflowMenuControl hasAdditionalOptions = { hasRegularActions } data-ouia-component-id = { `${ ouiaId } -menu-control` } >
77- < Dropdown
78- ouiaId = { `${ ouiaId } -menu-dropdown` }
79- onSelect = { ( ) => setIsOpen ( false ) }
80- toggle = { ( toggleRef ) => (
81- < MenuToggle
82- ouiaId = { `${ ouiaId } -menu-dropdown-toggle` }
83- ref = { toggleRef }
84- aria-label = "Actions overflow menu"
85- variant = "plain"
86- icon = { < EllipsisVIcon /> }
87- onClick = { ( ) => setIsOpen ( ! isOpen ) }
88- isExpanded = { isOpen }
89- />
90- ) }
91- isOpen = { isOpen }
92- onOpenChange = { setIsOpen }
93- >
94- < DropdownList data-ouia-component-id = { `${ ouiaId } -menu-dropdown-list` } >
95- { dropdownItems }
96- </ DropdownList >
97- </ Dropdown >
139+ < ResponsiveActionsDropdown
140+ ouiaId = { ouiaId }
141+ dropdownItems = { dropdownItems }
142+ pinnedItemsDisabled = { pinnedItemsDisabled }
143+ regularItemsDisabled = { regularItemsDisabled }
144+ />
98145 </ OverflowMenuControl >
99146 ) }
100147 </ OverflowMenu >
0 commit comments