mantinedev / mantine

A fully featured React components library
https://mantine.dev
MIT License
26.87k stars 1.9k forks source link

Tooltips on buttons persist when the button is disabled #4066

Closed ChapterSevenSeeds closed 1 year ago

ChapterSevenSeeds commented 1 year ago

What package has an issue

@mantine/core

Describe the bug

Consider the following code.

import React, { useState } from 'react';
import ReactDOM from 'react-dom/client';
import { Tooltip, Button} from "@mantine/core";

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

function App() {
  const [disabled, setDisabled] = useState(false);

  return (
    <Tooltip label="This is a tooltip">
      <Button disabled={disabled} onClick={() => setDisabled(!disabled)}>
        Click me
      </Button>
    </Tooltip>
  );
}

If you move the cursor over the Click me button, the tooltip appears. Then, if you click the button, the button becomes disabled but the tooltip persists.

What version of @mantine/hooks page do you have in package.json?

^6.0.7

If possible, please include a link to a codesandbox with the reproduced problem

https://codesandbox.io/s/staging-rain-bcl8dk?file=/src/App.tsx

Do you know how to fix the issue

No

Are you willing to participate in fixing this issue and create a pull request with the fix

Yes

Possible fix

No response

TeLoardBruh commented 1 year ago

you can check this in the document https://mantine.dev/core/button/#disabled-button-with-tooltip and also it reacts to issues that lead to this for more information you can read from this https://github.com/facebook/react/issues/18753

It is related to the disabling button not triggering the onMouseLeave event. So using data-disabled and adding a tag [ data-disabled] as this instead of using disabled boolean value.

import { MantineProvider, Tooltip, Button } from "@mantine/core";
import { useState } from "react";

export default function App() {
  const [disabled, setDisabled] = useState(false);
  return (
    <MantineProvider withGlobalStyles withNormalizeCSS>
      <Tooltip label="This is a tooltip">
        {disabled ? (
          <Button
            data-disabled
            sx={{ "&[data-disabled]": { pointerEvents: "all" } }}
            onClick={(event) => event.preventDefault()}
          >
            Click me
          </Button>
        ) : (
          <Button
            onClick={(event) => {
              setDisabled(!disabled);
            }}
          >
            Click me
          </Button>
        )}
      </Tooltip>
    </MantineProvider>
  );
}
ChapterSevenSeeds commented 1 year ago

Is there a plan in the Mantine roadmap to replace the onMouseEnter and onMouseLeave events with the suggested onPointerEnter and onPointerLeave events as described here? It seems like they are both now supported by all major browsers, as shown here.

TeLoardBruh commented 1 year ago

Is there a plan in the Mantine roadmap to replace the onMouseEnter and onMouseLeave events with the suggested onPointerEnter and onPointerLeave events as described here? It seems like they are both now supported by all major browsers, as shown here.

Going around the docs, I haven't found those yet (only mouse event). but I think we can do something around js to use the event here is the blog from React team https://reactnative.dev/blog/2022/12/13/pointer-events-in-react-native

image

TeLoardBruh commented 1 year ago

@ChapterSevenSeeds

the alternative solution, using onPointerEnter and onPointerLeave

import { MantineProvider, Tooltip, Button, Divider } from "@mantine/core";
import { useState } from "react";

export default function App() {
  const [disabled, setDisabled] = useState(false);
  const [disabledToolTip, setDisabledToolTip] = useState(false);
  const handlePointerEnter = () => {
    setDisabledToolTip(true);
  };
  const handlePointerLeave = () => {
    setDisabledToolTip(false);
  };
  return (
    <MantineProvider withGlobalStyles withNormalizeCSS>
      <Tooltip label="This is a tooltip">
        <Button disabled={disabled} onClick={() => setDisabled(!disabled)}>
          Click me
        </Button>
      </Tooltip>
      <Divider style={{ marginTop: "10px" }} />
      <Tooltip label="This is a tooltip" opened={disabledToolTip}>
        <Button
          onPointerEnter={handlePointerEnter}
          onPointerLeave={handlePointerLeave}
          disabled={disabled}
          onClick={() => setDisabled(!disabled)}
          style={{ marginTop: "10px" }}
        >
          Click me onPointerDown!
        </Button>
      </Tooltip>
    </MantineProvider>
  );
}
rtivital commented 1 year ago

It is not planned to change this behavior, see – https://github.com/floating-ui/floating-ui/discussions/1865#discussioncomment-3439773