elastic / eui

Elastic UI Framework 🙌
https://eui.elastic.co/
Other
6.08k stars 829 forks source link

EuiButtonIcon isLoading breaks EuiTooltip onBlur hide behavior #8014

Open kapral18 opened 1 week ago

kapral18 commented 1 week ago

Describe the bug If EuiButtonIcon has isLoading that is changing after click on the button the wrapping EuiToolTip stops hiding on blur.

Impact and severity Every single EuiButtonIcon wrapped in EuiToolTip. Specific UI that gets affected is new DataQuality dashboard introduced in 8.16 with new custom action table item index check button icon.

Environment and versions

To Reproduce Steps to reproduce the behavior:

  1. Click an EuiButtonIcon.
  2. Wait until a loader happens
  3. Hover away and click somewhere else
  4. See the tooltip not disappear Expected behavior Tooltip should disappear

Minimum reproducible example

import React, { useState, useCallback } from "react";
import { EuiToolTip, EuiButtonIcon } from "@elastic/eui";

export const Demo = () => {
  const [isLoading, setIsLoading] = useState<boolean>(false);

  const handleLoad = useCallback(() => {
    setIsLoading(true);

    setTimeout(() => {
      setIsLoading(false);
    }, 200);
  }, [setIsLoading]);

  return (
    <EuiToolTip content={"Check index"}>
      <EuiButtonIcon
        iconType="refresh"
        aria-label={"Check index"}
        isLoading={isLoading}
        onClick={handleLoad}
      />
    </EuiToolTip>
  );
};

Minimum reproducible sandbox codesandbox link

Screenshots https://github.com/user-attachments/assets/25a6236b-ccff-4ad3-abc9-f55ba0c926ed (23rd second when clicking away from focused button, tooltip stays)

cee-chen commented 2 days ago

This has been reported previously: https://github.com/elastic/eui/issues/6488

Unfortunately the answer is still essentially the same: EUI cannot detect any event when buttons are disabled at a React level: https://github.com/facebook/react/issues/9142

https://github.com/elastic/eui/issues/5666 would resolve this issue by not truly disabling buttons, but we don't have an ETA for this work although we do want to do it.

In the interim, one option would be to conditionally wrap your tooltip based on disabled status:

const sometimesDisabledButton = (
  <EuiButton disabled={isDisabled}>
    Button
  </EuiButton>
);

return (
  <>
    {isDisabled ? (
      sometimesDisabledButton
    ) : (
      <EuiToolTip content="Tooltip content">
        {sometimesDisabledButton}
      </EuiToolTip>
    )}
  </>
)