Skip to content

Commit

Permalink
Merge pull request #111 from mondaycom/feature/moshe/menu_item_button
Browse files Browse the repository at this point in the history
Feature/moshe/menu item button
  • Loading branch information
MosheZemah authored Apr 26, 2021
2 parents 5ef99d0 + 63ac06d commit 5b9ebbd
Show file tree
Hide file tree
Showing 10 changed files with 519 additions and 9 deletions.
12 changes: 9 additions & 3 deletions src/components/Button/Button.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ const Button = forwardRef(
defaultTextColorOnPrimaryColor,
ariaHasPopup,
ariaExpanded,
ariaControls
ariaControls,
blurOnMouseUp
},
ref
) => {
Expand Down Expand Up @@ -89,8 +90,10 @@ const Button = forwardRef(
if (!button) {
return;
}
button.blur();
}, [buttonRef]);
if (blurOnMouseUp) {
button.blur();
}
}, [buttonRef, blurOnMouseUp]);

const onButtonClicked = useCallback(
event => {
Expand Down Expand Up @@ -265,6 +268,8 @@ Button.propTypes = {
kind: PropTypes.oneOf([Button.kinds.PRIMARY, Button.kinds.SECONDARY, Button.kinds.TERTIARY]),
onClick: PropTypes.func,
onMouseDown: PropTypes.func,
/** Blur on button click */
blurOnMouseUp: PropTypes.bool,
/** Name of the button - for form submit usages */
name: PropTypes.string,
/** The size of a button is exposed on the component */
Expand Down Expand Up @@ -332,6 +337,7 @@ Button.defaultProps = {
kind: BUTTON_TYPES.PRIMARY,
onClick: NOOP,
onMouseDown: NOOP,
blurOnMouseUp: true,
name: undefined,
style: undefined,
size: SIZES.MEDIUM,
Expand Down
6 changes: 2 additions & 4 deletions src/components/Menu/MenuItem/MenuItem.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -193,9 +193,6 @@ const MenuItem = ({
>
{renderMenuItemIconIfNeeded()}

{// show tooltip if needed
isTitleHoveredAndOverflowing && null}

<div ref={titleRef} className="monday-style-menu-item__title">
{title}
</div>
Expand Down Expand Up @@ -234,7 +231,7 @@ MenuItem.iconType = Icon.type;
MenuItem.defaultProps = {
classname: "",
title: "",
lebel: "",
label: "",
icon: "",
iconType: undefined,
disabled: false,
Expand All @@ -256,6 +253,7 @@ MenuItem.defaultProps = {
MenuItem.propTypes = {
classname: PropTypes.string,
title: PropTypes.string,
label: PropTypes.string,
icon: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
iconType: PropTypes.oneOf([Icon.type.SVG, Icon.type.ICON_FONT]),
disabled: PropTypes.bool,
Expand Down
32 changes: 32 additions & 0 deletions src/components/Menu/MenuItemButton/MenuItemButton-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import React from "react";
import { render, cleanup } from "@testing-library/react";
import { expect } from "../../../test/test-helpers";
import MenuItem from "./MenuItem";

describe("<MenuItem />", () => {
afterEach(() => {
cleanup();
});

it("should be able to render menu item", () => {
const { container } = render(<MenuItem />);
});

it("should be able to render menu item text", () => {
const { container } = render(<MenuItem title="my item title" icon="fa fa-star" />);
const menuItemElement = container.querySelector(".monday-style-menu-item");
expect(menuItemElement.innerText).to.eq("my item title");
});

describe("render children inside popover element", () => {
it("should be able to render children ", () => {
const { container } = render(
<MenuItem title="my item title" icon="fa fa-star">
<div className="bla-element">Bla bla bla</div>
</MenuItem>
);
const childElement = container.querySelector(".bla-element");
expect(childElement.innerText).to.eq("Bla bla bla");
});
});
});
135 changes: 135 additions & 0 deletions src/components/Menu/MenuItemButton/MenuItemButton.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
/* eslint-disable react/jsx-props-no-spreading */
import React, { useRef } from "react";

import PropTypes from "prop-types";
import cx from "classnames";
import Button from "../../Button/Button";
import Tooltip from "../../Tooltip/Tooltip";

import useMergeRefs from "../../../hooks/useMergeRefs";

import useMenuItemMouseEvents from "../MenuItem/hooks/useMenuItemMouseEvents";
import useMenuItemKeyboardEvents from "../MenuItem/hooks/useMenuItemKeyboardEvents";

import "./MenuItemButton.scss";

const MenuItemButton = ({
classname,
kind,
leftIcon,
rightIcon,
disabled,
disableReason,
index,
activeItemIndex,
onClick,
menuId,
tooltipPosition,
tooltipShowDelay,
children,
resetOpenSubMenuIndex,
setSubMenuIsOpenByIndex,
setActiveItemIndex,
menuRef,
closeMenu,
useDocumentEventListeners
}) => {
const ref = useRef(null);
const referenceElementRef = useRef(null);

const mergedRef = useMergeRefs({ refs: [ref, referenceElementRef] });

const shouldShowTooltip = disabled && disableReason;
const tooltipContent = disableReason;

const isActive = activeItemIndex === index;

const isMouseEnter = useMenuItemMouseEvents(
ref,
resetOpenSubMenuIndex,
setSubMenuIsOpenByIndex,
isActive,
setActiveItemIndex,
index,
false
);

const { onClickCallback } = useMenuItemKeyboardEvents(
onClick,
disabled,
isActive,
index,
setActiveItemIndex,
false,
false,
setSubMenuIsOpenByIndex,
menuRef,
isMouseEnter,
closeMenu,
useDocumentEventListeners
);

return (
<Tooltip
content={shouldShowTooltip ? tooltipContent : null}
position={tooltipPosition}
showDelay={tooltipShowDelay}
>
<li
id={`${menuId}-${index}`}
className={cx("monday-style-menu-item-button", classname)}
ref={mergedRef}
role="menuitem"
aria-current={isActive}
>
<Button
active={isActive}
disabled={disabled}
leftIcon={leftIcon}
rightIcon={rightIcon}
onClick={onClickCallback}
kind={kind}
size={Button.sizes.SMALL}
blurOnMouseUp={false}
>
<div className="menu-item-button-content">{children}</div>
</Button>
</li>
</Tooltip>
);
};

MenuItemButton.kinds = Button.kinds;

MenuItemButton.defaultProps = {
classname: "",
kind: MenuItemButton.kinds.PRIMARY,
leftIcon: null,
rightIcon: null,
index: undefined,
activeItemIndex: -1,
disabled: false,
disableReason: undefined,
onClick: undefined,
tooltipPosition: "right",
tooltipShowDelay: 300
};

MenuItemButton.propTypes = {
classname: PropTypes.string,
kind: PropTypes.oneOf([MenuItemButton.kinds.PRIMARY, MenuItemButton.kinds.SECONDARY, MenuItemButton.kinds.TERTIARY]),
leftIcon: PropTypes.string,
rightIcon: PropTypes.string,
index: PropTypes.number,
activeItemIndex: PropTypes.number,
disabled: PropTypes.bool,
disableReason: PropTypes.string,
onClick: PropTypes.func,
tooltipPosition: PropTypes.oneOf("right", "left", "top", "bottom"),
tooltipShowDelay: PropTypes.number
};

MenuItemButton.isSelectable = true;
MenuItemButton.isMenuChild = true;

export default MenuItemButton;
21 changes: 21 additions & 0 deletions src/components/Menu/MenuItemButton/MenuItemButton.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
@import "../../../styles/themes.scss";
@import "../../../styles/typography.scss";

.monday-style-menu-item-button {
margin: unset;
@include font-default;
display: flex;
flex-direction: row;
padding: $spacing-xs 0;
align-items: center;

.monday-style-button {
width: 100%;

.menu-item-button-content {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
}
Loading

0 comments on commit 5b9ebbd

Please sign in to comment.