Skip to content

Commit bc888ca

Browse files
rhamiltoclaude
andcommitted
fix(ResponsiveActions): prevent empty dropdown when all actions are persistent or pinned
Fixes #888 When all ResponsiveAction components had isPersistent or isPinned props, an empty kebab dropdown was still being rendered. Changes: - Removed hasAdditionalOptions prop from OverflowMenuControl to let PatternFly's OverflowMenu manage dropdown visibility based on content - Added early return guard to prevent rendering empty OverflowMenu - Added tests for persistent-only, pinned-only, and mixed action scenarios Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent 24a7dff commit bc888ca

File tree

3 files changed

+165
-29
lines changed

3 files changed

+165
-29
lines changed

packages/module/src/ResponsiveActions/ResponsiveActions.test.tsx

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,47 @@ describe('ResponsiveActions component', () => {
1414
</ResponsiveActions>);
1515
expect(container).toMatchSnapshot();
1616
});
17+
18+
test('ResponsiveActions with only isPersistent actions', () => {
19+
const { container } = render(
20+
<ResponsiveActions breakpoint="lg">
21+
<ResponsiveAction isPersistent>Persistent action 1</ResponsiveAction>
22+
<ResponsiveAction isPersistent>Persistent action 2</ResponsiveAction>
23+
</ResponsiveActions>);
24+
25+
// Should not have dropdown control when only persistent actions
26+
const dropdownControl = container.querySelector('[data-ouia-component-id="ResponsiveActions-menu-control"]');
27+
expect(dropdownControl).toBeNull();
28+
29+
// Should have persistent actions
30+
const buttons = container.querySelectorAll('button');
31+
expect(buttons).toHaveLength(2);
32+
});
33+
34+
test('ResponsiveActions with only isPinned actions', () => {
35+
const { container } = render(
36+
<ResponsiveActions breakpoint="lg">
37+
<ResponsiveAction isPinned>Pinned action 1</ResponsiveAction>
38+
<ResponsiveAction isPinned>Pinned action 2</ResponsiveAction>
39+
</ResponsiveActions>);
40+
41+
// Should have pinned actions as buttons
42+
const buttons = container.querySelectorAll('button');
43+
expect(buttons).toHaveLength(2);
44+
expect(container).toMatchSnapshot();
45+
});
46+
47+
test('ResponsiveActions with mix of isPersistent and isPinned actions', () => {
48+
const { container } = render(
49+
<ResponsiveActions breakpoint="lg">
50+
<ResponsiveAction isPersistent>Persistent action</ResponsiveAction>
51+
<ResponsiveAction isPinned>Pinned action</ResponsiveAction>
52+
</ResponsiveActions>);
53+
54+
// Should have both persistent and pinned actions as buttons
55+
const buttons = container.querySelectorAll('button');
56+
expect(buttons).toHaveLength(2);
57+
expect(container).toMatchSnapshot();
58+
});
1759
});
1860
});

packages/module/src/ResponsiveActions/ResponsiveActions.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,11 @@ export const ResponsiveActions: FunctionComponent<ResponsiveActionsProps> = ({ o
4545
}
4646
});
4747

48+
// Only render OverflowMenu if there are actions to display
49+
if (persistentActions.length === 0 && pinnedActions.length === 0 && dropdownItems.length === 0) {
50+
return null;
51+
}
52+
4853
return (
4954
<OverflowMenu breakpoint={breakpoint} data-ouia-component-id={`${ouiaId}-menu`} {...props}>
5055
{persistentActions.length > 0 ? (
@@ -62,7 +67,7 @@ export const ResponsiveActions: FunctionComponent<ResponsiveActionsProps> = ({ o
6267
</OverflowMenuContent>
6368
) : null}
6469
{dropdownItems.length > 0 && (
65-
<OverflowMenuControl hasAdditionalOptions data-ouia-component-id={`${ouiaId}-menu-control`}>
70+
<OverflowMenuControl data-ouia-component-id={`${ouiaId}-menu-control`}>
6671
<Dropdown
6772
ouiaId={`${ouiaId}-menu-dropdown`}
6873
onSelect={() => setIsOpen(false)}

packages/module/src/ResponsiveActions/__snapshots__/ResponsiveActions.test.tsx.snap

Lines changed: 117 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -62,39 +62,128 @@ exports[`ResponsiveActions component should render correctly ResponsiveActions 1
6262
</div>
6363
</div>
6464
</div>
65+
</div>
66+
</div>
67+
`;
68+
69+
exports[`ResponsiveActions component should render correctly ResponsiveActions with mix of isPersistent and isPinned actions 1`] = `
70+
<div>
71+
<div
72+
class="pf-v6-c-overflow-menu"
73+
data-ouia-component-id="ResponsiveActions-menu"
74+
>
6575
<div
66-
class="pf-v6-c-overflow-menu__control"
67-
data-ouia-component-id="ResponsiveActions-menu-control"
76+
class="pf-v6-c-overflow-menu__content"
6877
>
69-
70-
<button
71-
aria-expanded="false"
72-
aria-label="Actions overflow menu"
73-
class="pf-v6-c-menu-toggle pf-m-plain"
74-
data-ouia-component-id="ResponsiveActions-menu-dropdown-toggle"
75-
data-ouia-component-type="PF6/MenuToggle"
76-
data-ouia-safe="true"
77-
type="button"
78+
<div
79+
class="pf-v6-c-overflow-menu__group pf-m-button-group"
80+
data-ouia-component-id="ResponsiveActions-menu-persistent-group"
7881
>
79-
<span
80-
class="pf-v6-c-menu-toggle__icon"
82+
<div
83+
class="pf-v6-c-overflow-menu__item"
8184
>
82-
<svg
83-
aria-hidden="true"
84-
class="pf-v6-svg"
85-
fill="currentColor"
86-
height="1em"
87-
role="img"
88-
viewBox="0 0 192 512"
89-
width="1em"
85+
86+
<button
87+
class="pf-v6-c-button pf-m-primary"
88+
data-ouia-component-id="ResponsiveActions-action-0"
89+
data-ouia-component-type="PF6/Button"
90+
data-ouia-safe="true"
91+
type="button"
9092
>
91-
<path
92-
d="M96 184c39.8 0 72 32.2 72 72s-32.2 72-72 72-72-32.2-72-72 32.2-72 72-72zM24 80c0 39.8 32.2 72 72 72s72-32.2 72-72S135.8 8 96 8 24 40.2 24 80zm0 352c0 39.8 32.2 72 72 72s72-32.2 72-72-32.2-72-72-72-72 32.2-72 72z"
93-
/>
94-
</svg>
95-
</span>
96-
</button>
97-
93+
<span
94+
class="pf-v6-c-button__text"
95+
>
96+
Persistent action
97+
</span>
98+
</button>
99+
100+
</div>
101+
</div>
102+
</div>
103+
<div
104+
class="pf-v6-c-overflow-menu__content"
105+
>
106+
<div
107+
class="pf-v6-c-overflow-menu__group pf-m-button-group"
108+
data-ouia-component-id="ResponsiveActions-menu-pinned-group"
109+
>
110+
<div
111+
class="pf-v6-c-overflow-menu__item"
112+
>
113+
114+
<button
115+
class="pf-v6-c-button pf-m-primary"
116+
data-ouia-component-id="ResponsiveActions-action-1"
117+
data-ouia-component-type="PF6/Button"
118+
data-ouia-safe="true"
119+
type="button"
120+
>
121+
<span
122+
class="pf-v6-c-button__text"
123+
>
124+
Pinned action
125+
</span>
126+
</button>
127+
128+
</div>
129+
</div>
130+
</div>
131+
</div>
132+
</div>
133+
`;
134+
135+
exports[`ResponsiveActions component should render correctly ResponsiveActions with only isPinned actions 1`] = `
136+
<div>
137+
<div
138+
class="pf-v6-c-overflow-menu"
139+
data-ouia-component-id="ResponsiveActions-menu"
140+
>
141+
<div
142+
class="pf-v6-c-overflow-menu__content"
143+
>
144+
<div
145+
class="pf-v6-c-overflow-menu__group pf-m-button-group"
146+
data-ouia-component-id="ResponsiveActions-menu-pinned-group"
147+
>
148+
<div
149+
class="pf-v6-c-overflow-menu__item"
150+
>
151+
152+
<button
153+
class="pf-v6-c-button pf-m-primary"
154+
data-ouia-component-id="ResponsiveActions-action-0"
155+
data-ouia-component-type="PF6/Button"
156+
data-ouia-safe="true"
157+
type="button"
158+
>
159+
<span
160+
class="pf-v6-c-button__text"
161+
>
162+
Pinned action 1
163+
</span>
164+
</button>
165+
166+
</div>
167+
<div
168+
class="pf-v6-c-overflow-menu__item"
169+
>
170+
171+
<button
172+
class="pf-v6-c-button pf-m-primary"
173+
data-ouia-component-id="ResponsiveActions-action-1"
174+
data-ouia-component-type="PF6/Button"
175+
data-ouia-safe="true"
176+
type="button"
177+
>
178+
<span
179+
class="pf-v6-c-button__text"
180+
>
181+
Pinned action 2
182+
</span>
183+
</button>
184+
185+
</div>
186+
</div>
98187
</div>
99188
</div>
100189
</div>

0 commit comments

Comments
 (0)