Skip to content

Commit

Permalink
feat(multi-action-button): add position prop
Browse files Browse the repository at this point in the history
Adds position prop to allow consumers to specify on which side the menu is aligned to when opened.

fix #6705
  • Loading branch information
nuria1110 committed May 8, 2024
1 parent f1991b4 commit e29b588
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export interface MultiActionButtonProps

export const MultiActionButton = ({
align = "left",
position = "left",
disabled,
buttonType,
size,
Expand Down Expand Up @@ -78,7 +79,10 @@ export const MultiActionButton = ({
};

const renderAdditionalButtons = () => (
<Popover placement="bottom-end" reference={buttonNode}>
<Popover
placement={position === "left" ? "bottom-start" : "bottom-end"}
reference={buttonNode}
>
<StyledButtonChildrenContainer {...wrapperProps} align={align}>
<SplitButtonContext.Provider value={contextValue}>
{React.Children.map(children, (child) => (
Expand Down
12 changes: 11 additions & 1 deletion src/components/multi-action-button/multi-action-button.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,20 @@ Buttons used as a content of `MultiActionButton` can be of any type.

<Canvas of={MultiActionButtonStories.Sizes} />

### Alignment
### Button text alignment

Use the `align` prop to change the alignment of the text in the menu Buttons.

<Canvas of={MultiActionButtonStories.Alignment} />

### Menu position

By default, the menu will open aligned to the left of the button, but you can use the `position` prop to change this to the right.

Note: The position of the menu will also be automatically adjusted to fit within the viewport.

<Canvas of={MultiActionButtonStories.Position} />

### Subtext

Subtext only works when `size` is `large`
Expand Down
23 changes: 22 additions & 1 deletion src/components/multi-action-button/multi-action-button.pw.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ test.describe("Prop tests", () => {

(["left", "right"] as MultiActionButtonProps["align"][]).forEach(
(alignment) => {
test(`should render with button aligned to the ${alignment}`, async ({
test(`should render with button text aligned to the ${alignment}`, async ({
mount,
page,
}) => {
Expand All @@ -104,6 +104,27 @@ test.describe("Prop tests", () => {
}
);

([
["left", 200],
["right", 153],
] as [MultiActionButtonProps["position"], number][]).forEach(
([position, value]) => {
test(`should render with menu position to the ${position}`, async ({
mount,
page,
}) => {
await mount(<MultiActionButtonList ml="200px" position={position} />);

const actionButton = getComponent(page, "multi-action-button");
await actionButton.click();
const listContainer = getDataElementByValue(page, "additional-buttons");
await expect(listContainer).toHaveCSS("position", "absolute");
await assertCssValueIsApproximately(listContainer, "top", 40);
await assertCssValueIsApproximately(listContainer, "left", value);
});
}
);

test(`should render with button disabled`, async ({ mount, page }) => {
await mount(<MultiActionButtonList disabled />);

Expand Down
16 changes: 16 additions & 0 deletions src/components/multi-action-button/multi-action-button.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
} from "../../__spec_helper__/test-utils";
import StyledButton from "../button/button.style";
import StyledIcon from "../icon/icon.style";
import Popover from "../../__internal__/popover";

// eslint-disable-next-line @typescript-eslint/no-explicit-any
function render(props = {}, renderer: any = shallow) {
Expand Down Expand Up @@ -645,6 +646,21 @@ describe("MultiActionButton", () => {
});
});

describe("position prop", () => {
it.each([
["bottom-start", "left"],
["bottom-end", "right"],
])(
"should have placement set to %s when position prop is %s",
(placement, positionValue) => {
wrapper = render({ position: positionValue }, mount);
openAdditionalButtons(wrapper);

expect(wrapper.find(Popover).props().placement).toEqual(placement);
}
);
});

it("should set proper width of ButtonContainer", () => {
const getBoundingClientRectMock = jest
.spyOn(Element.prototype, "getBoundingClientRect")
Expand Down
20 changes: 20 additions & 0 deletions src/components/multi-action-button/multi-action-button.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,26 @@ export const Alignment: Story = () => {
Alignment.storyName = "Alignment";
Alignment.parameters = { chromatic: { disableSnapshot: true } };

export const Position: Story = () => {
return (
<Box display="flex" justifyContent="space-around">
<MultiActionButton position="left" text="Left position">
<Button href="#">Button 1 with longer text</Button>
<Button>Button 2</Button>
<Button>Button 3</Button>
</MultiActionButton>

<MultiActionButton position="right" text="Right position">
<Button href="#">Button 1 with longer text</Button>
<Button>Button 2</Button>
<Button>Button 3</Button>
</MultiActionButton>
</Box>
);
};
Position.storyName = "Position";
Position.parameters = { chromatic: { disableSnapshot: true } };

export const Subtext: Story = {
...DefaultStory,
args: {
Expand Down

0 comments on commit e29b588

Please sign in to comment.