Repository: mui/material-ui (TypeScript) — Bug Fix

Issue:
[ButtonBase] Right clicking stack up ripples
- [x] The issue is present in the latest release.
- [x] I have searched the [issues](https://github.com/mui-org/material-ui/issues) of this repository and believe that this is not a duplicate.

## Current Behavior 😯

When I right click a component that has the typical material design click behavior, the color of this reaction adds up. So when the tinting is grey the component gets black. When the tinting is white it gets completely white.

## Expected Behavior 🤔

When I right click it, the tint can stay as long as the context menu is open. But then it should go away slowly. Or when clicked after a right click, it does not "add up".

https://user-images.githubusercontent.com/41862965/108120899-3f10a380-70a2-11eb-8a14-aa075f510a14.mov

## Steps to Reproduce 🕹

Steps:

1. https://codesandbox.io/s/issue-c54tu

## Context 🔦

No problem but it is a strange behavior.

## Your Environment 🌎

Safari and Chrome.

    "@material-ui/core": "^4.11.3",
    "@material-ui/icons": "^4.11.2",

<details>
  <summary>`npx @material-ui/envinfo`</summary>
  
System:
    OS: macOS 11.2.1
    CPU: (8) x64 Intel(R) Core(TM) i5-8257U CPU @ 1.40GHz
    Memory: 107.60 MB / 8.00 GB
    Shell: 5.8 - /bin/zsh
  Binaries:
    Node: 14.15.4 - /usr/local/bin/node
    npm: 7.5.4 - /usr/local/bin/npm
    Watchman: 4.9.0 - /usr/local/bin/watchman
  Managers:
    CocoaPods: 1.10.1 - /usr/local/bin/pod
    Homebrew: 3.0.0 - /usr/local/bin/brew
    pip3: 21.0.1 - /usr/local/bin/pip3
    RubyGems: 3.0.3 - /usr/bin/gem
  Utilities:
    Make: 3.81 - /usr/bin/make
    GCC: 4.2.1 - /usr/bin/gcc
    Git: 2.24.3 - /usr/bin/git
    Clang: 1200.0.32.2 - /usr/bin/clang
  Servers:
    Apache: 2.4.46 - /usr/sbin/apachectl
  SDKs:
    iOS SDK:
      Platforms: iOS 14.0, DriverKit 19.0, macOS 10.15, tvOS 14.0, watchOS 7.0
  IDEs:
    Nano: 2.0.6 - /usr/bin/nano
    Vim: 8.2 - /usr/bin/vim
    Xcode: 12.0.1/12A7300 - /usr/bin/xcodebuild
  Languages:
    Bash: 3.2.57 - /bin/bash
    Perl: 5.28.2 - /usr/bin/perl
    PHP: 7.3.24 - /usr/bin/php
    Python: 2.7.16 - /usr/bin/python
    Python3: 3.9.1 - /usr/local/bin/python3
    Ruby: 2.6.3 - /usr/bin/ruby
  Databases:
    SQLite: 3.32.3 - /usr/bin/sqlite3
  Browsers:
    Chrome: 84.0.4147.135
    Safari: 14.0.3
</details>



Discussion:
It doesn't look like this bug report has enough info for one of us to reproduce it.

Please provide a CodeSandbox (https://material-ui.com/r/issue-template-latest), a link to a repository on GitHub, or provide a minimal code example that reproduces the problem. 

Here are some tips for providing a minimal example: https://stackoverflow.com/help/mcve

<!-- mui template next: https://material-ui.com/r/issue-template-next -->
<!-- mui template stable: https://material-ui.com/r/issue-template-latest -->
<!-- react template: https://react.new/ -->

Resolving patch:
diff --git a/packages/material-ui/src/ButtonBase/ButtonBase.js b/packages/material-ui/src/ButtonBase/ButtonBase.js
--- a/packages/material-ui/src/ButtonBase/ButtonBase.js
+++ b/packages/material-ui/src/ButtonBase/ButtonBase.js
@@ -88,6 +88,7 @@ const ButtonBase = React.forwardRef(function ButtonBase(inProps, ref) {
     focusVisibleClassName,
     onBlur,
     onClick,
+    onContextMenu,
     onFocus,
     onFocusVisible,
     onKeyDown,
@@ -155,6 +156,7 @@ const ButtonBase = React.forwardRef(function ButtonBase(inProps, ref) {
   }
 
   const handleMouseDown = useRippleHandler('start', onMouseDown);
+  const handleContextMenu = useRippleHandler('stop', onContextMenu);
   const handleDragLeave = useRippleHandler('stop', onDragLeave);
   const handleMouseUp = useRippleHandler('stop', onMouseUp);
   const handleMouseLeave = useRippleHandler('stop', (event) => {
@@ -346,6 +348,7 @@ const ButtonBase = React.forwardRef(function ButtonBase(inProps, ref) {
       styleProps={styleProps}
       onBlur={handleBlur}
       onClick={onClick}
+      onContextMenu={handleContextMenu}
       onFocus={handleFocus}
       onKeyDown={handleKeyDown}
       onKeyUp={handleKeyUp}
@@ -454,6 +457,10 @@ ButtonBase.propTypes = {
    * @ignore
    */
   onClick: PropTypes.func,
+  /**
+   * @ignore
+   */
+  onContextMenu: PropTypes.func,
   /**
    * @ignore
    */


Test patch:
diff --git a/packages/material-ui/src/ButtonBase/ButtonBase.test.js b/packages/material-ui/src/ButtonBase/ButtonBase.test.js
--- a/packages/material-ui/src/ButtonBase/ButtonBase.test.js
+++ b/packages/material-ui/src/ButtonBase/ButtonBase.test.js
@@ -119,6 +119,7 @@ describe('<ButtonBase />', () => {
       const onMouseDown = spy();
       const onMouseLeave = spy();
       const onMouseUp = spy();
+      const onContextMenu = spy();
       const onDragEnd = spy();
       const onTouchStart = spy();
       const onTouchEnd = spy();
@@ -133,6 +134,7 @@ describe('<ButtonBase />', () => {
           onMouseDown={onMouseDown}
           onMouseLeave={onMouseLeave}
           onMouseUp={onMouseUp}
+          onContextMenu={onContextMenu}
           onDragEnd={onDragEnd}
           onTouchEnd={onTouchEnd}
           onTouchStart={onTouchStart}
@@ -164,6 +166,9 @@ describe('<ButtonBase />', () => {
       fireEvent.mouseUp(button);
       expect(onMouseUp.callCount).to.equal(1);
 
+      fireEvent.contextMenu(button);
+      expect(onContextMenu.callCount).to.equal(1);
+
       fireEvent.click(button);
       expect(onClick.callCount).to.equal(1);
 
@@ -375,6 +380,34 @@ describe('<ButtonBase />', () => {
         ).to.have.lengthOf(0);
       });
 
+      it('should stop the ripple when the context menu opens', () => {
+        const { getByRole } = render(
+          <ButtonBase
+            TouchRippleProps={{
+              classes: {
+                rippleVisible: 'ripple-visible',
+                child: 'child',
+                childLeaving: 'child-leaving',
+              },
+            }}
+          />,
+        );
+        const button = getByRole('button');
+        fireEvent.mouseDown(button);
+
+        expect(button.querySelectorAll('.ripple-visible .child-leaving')).to.have.lengthOf(0);
+        expect(
+          button.querySelectorAll('.ripple-visible .child:not(.child-leaving)'),
+        ).to.have.lengthOf(1);
+
+        fireEvent.contextMenu(button);
+
+        expect(button.querySelectorAll('.ripple-visible .child-leaving')).to.have.lengthOf(1);
+        expect(
+          button.querySelectorAll('.ripple-visible .child:not(.child-leaving)'),
+        ).to.have.lengthOf(0);
+      });
+
       it('should not crash when changes enableRipple from false to true', () => {
         function App() {
           /** @type {React.MutableRefObject<import('./ButtonBase').ButtonBaseActions | null>} */