Skip to content

Commit c23a763

Browse files
author
Konstantinos Familonidis
committed
Fixes #38822: update pf3 buttons to pf5 - common/ActionButtons
1 parent 95b122d commit c23a763

File tree

5 files changed

+107
-73
lines changed

5 files changed

+107
-73
lines changed
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { noop } from '../../../common/helpers';
22

33
export const buttons = [
4-
{ title: 'first', action: { onClick: noop } },
5-
{ title: 'second', action: { href: 'some-url2', 'data-method': 'put' } },
6-
{ title: 'third', action: { onClick: noop } },
4+
{ title: 'first', action: { id: 1, onClick: noop } },
5+
{ title: 'second', action: { id: 2, href: 'some-url2', 'data-method': 'put' } },
6+
{ title: 'third', action: { id: 3, onClick: noop } },
77
];

webpack/assets/javascripts/react_app/components/common/ActionButtons/ActionButtons.js

Lines changed: 64 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,83 @@
1-
import React from 'react';
1+
import React, { useState } from 'react';
22
import PropTypes from 'prop-types';
3-
import { SplitButton, MenuItem, Button } from 'patternfly-react';
3+
import {
4+
Button,
5+
Dropdown,
6+
DropdownItem,
7+
DropdownList,
8+
MenuToggle,
9+
MenuToggleAction,
10+
} from '@patternfly/react-core';
11+
import './actionButtons.scss';
412

513
/**
614
* Generate a button or a dropdown of buttons
715
* @param {String} title The title of the button for the title and text inside the button
816
* @param {Object} action action to preform when the button is click can be href with data-method or Onclick
9-
* @return {Function} button component or splitbutton component
17+
* @return {Function} button component or dropdown with menu toggle action component
1018
*/
1119
export const ActionButtons = ({ buttons }) => {
20+
const [isOpen, setIsOpen] = useState(false);
21+
const onToggleClick = () => setIsOpen(!isOpen);
22+
const getUniqueId = () => Math.floor(Math.random() * 1_000) + 1;
23+
1224
if (!buttons.length) return null;
1325
if (buttons.length === 1)
1426
return (
15-
<Button bsSize="small" {...buttons[0].action}>
27+
<Button
28+
ouiaId="action-button"
29+
size="sm"
30+
variant="primary"
31+
{...buttons[0].action}
32+
>
1633
{buttons[0].title}
1734
</Button>
1835
);
19-
const firstButton = buttons.shift();
36+
37+
const [firstButton, ...restButtons] = buttons;
38+
const actionId = firstButton.action?.id || getUniqueId();
39+
2040
return (
21-
<SplitButton
22-
title={firstButton.title}
23-
{...firstButton.action}
24-
bsSize="small"
41+
<Dropdown
42+
ouiaId="action-buttons-dropdown"
43+
isOpen={isOpen}
44+
onOpenChange={openState => setIsOpen(openState)}
45+
toggle={toggleRef => (
46+
<MenuToggle
47+
ref={toggleRef}
48+
onClick={onToggleClick}
49+
isExpanded={isOpen}
50+
splitButtonOptions={{
51+
variant: 'action',
52+
items: [
53+
<MenuToggleAction
54+
id={`split-button-action-${actionId}-toggle-button`}
55+
key="split-action"
56+
aria-label={firstButton.title}
57+
onClick={firstButton.action?.onClick}
58+
>
59+
{firstButton.title}
60+
</MenuToggleAction>,
61+
],
62+
}}
63+
aria-label="Menu toggle with action split button"
64+
/>
65+
)}
66+
shouldFocusToggleOnSelect
2567
>
26-
{buttons.map(button => (
27-
<MenuItem key={button.title} title={button.title} {...button.action}>
28-
{button.title}
29-
</MenuItem>
30-
))}
31-
</SplitButton>
68+
<DropdownList className="action-buttons">
69+
{restButtons.map(button => (
70+
<DropdownItem
71+
ouiaId={`${button.action?.id || getUniqueId()}-dropdown-item-id`}
72+
key={`${button.action?.id || getUniqueId()}-dropdown-item-key`}
73+
title={button.title}
74+
onClick={button.action?.onClick}
75+
>
76+
{button.title}
77+
</DropdownItem>
78+
))}
79+
</DropdownList>
80+
</Dropdown>
3281
);
3382
};
3483

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,41 @@
1-
import { testComponentSnapshotsWithFixtures } from 'foremanReact/common/testHelpers';
1+
import React from 'react';
2+
import { screen, fireEvent, render, act } from '@testing-library/react';
3+
import '@testing-library/jest-dom/extend-expect';
4+
25
import { ActionButtons } from './ActionButtons';
36
import { buttons } from './ActionButtons.fixtures';
47

58
const fixtures = {
6-
'renders ActionButtons with 0 button': { buttons: [] },
7-
'renders ActionButtons with 1 button': { buttons: [buttons[0]] },
8-
'renders ActionButtons with 3 button': { buttons },
9+
none: { buttons: [] },
10+
one: { buttons: [buttons[0]] },
11+
many: { buttons },
912
};
1013

11-
describe('ActionButtons', () =>
12-
testComponentSnapshotsWithFixtures(ActionButtons, fixtures));
14+
describe('ActionButtons', () => {
15+
it('renders with 0 buttons', () => {
16+
render(<ActionButtons {...fixtures.none} />);
17+
expect(screen.queryByRole('button')).not.toBeInTheDocument();
18+
});
19+
20+
it('renders 1 button', () => {
21+
render(<ActionButtons {...fixtures.one} />);
22+
expect(screen.getByRole('button')).toHaveTextContent('first');
23+
});
24+
25+
it('renders 2 buttons initially and shows more after clicking toggle', async () => {
26+
render(<ActionButtons {...fixtures.many} />);
27+
const buttons = screen.getAllByRole('button');
28+
expect(buttons).toHaveLength(2);
29+
expect(screen.getByRole('button', { name: 'first' })).toBeInTheDocument();
30+
const toggleButton = screen.getByRole('button', {
31+
name: 'Menu toggle with action split button'
32+
});
33+
expect(toggleButton).toBeInTheDocument();
34+
35+
expect(screen.queryByText('second')).not.toBeInTheDocument();
36+
expect(screen.queryByText('third')).not.toBeInTheDocument();
37+
await act(async () => fireEvent.click(toggleButton));
38+
expect(screen.getByText('second')).toBeInTheDocument();
39+
expect(screen.getByText('third')).toBeInTheDocument();
40+
});
41+
});

webpack/assets/javascripts/react_app/components/common/ActionButtons/__snapshots__/ActionButtons.test.js.snap

Lines changed: 0 additions & 49 deletions
This file was deleted.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
.pf-v5-c-menu__content {
2+
ul[role="menu"].action-buttons {
3+
margin-bottom: 0;
4+
}
5+
}

0 commit comments

Comments
 (0)