Repository: equinor/design-system (ts)

Issue:
Tooltip flicker when hovering button or chip
**Describe the bug**

After upgrading from eds-core-react 0.40.1 to 0.42.4, we noticed that our tooltips have started flickering.
This happens when I hover the button, but the flickering stops when I hover the Icon on the button.
Also, tooltips on chips flicker all the time when the chip is hovered.

**Steps to reproduce the bug**

1. Add a button with an icon or a chip and wrap the button/chip in a tooltip
```html
<Tooltip title={'test'} placement="bottom">
  <Button variant={'ghost'}>
    This is a test <Icon data={comment} />
  </Button>
</Tooltip>
``` 

2. Hover the button text then hover the icon
3. The tooltip flickers every time you move your mouse or when hovering over a chip

**Expected behavior**

Expect the tooltip to stay still

**Specifications**

- Version: 0.42.4 / 0.42.5 (tried both)
- Browser: chrome
- OS: Windows

**Additional context**

Add any other context or screenshots about the bug. An example in [CodeSandbox](https://codesandbox.io/) is very helpful


Pull request description:
🐛 Tooltip: attempt to fix flicker issue
resolves #3694 

I will make a `next` release from this branch first so the reporter of the bug can test if the issue is resolved

Patch:
diff --git a/packages/eds-core-react/package.json b/packages/eds-core-react/package.json
index 5ccb644a..233b8e8a 100644
--- a/packages/eds-core-react/package.json
+++ b/packages/eds-core-react/package.json
@@ -96,7 +96,7 @@
     "@react-stately/calendar": "^3.5.3",
     "@react-stately/datepicker": "^3.10.1",
     "@react-types/shared": "^3.24.1",
-    "@tanstack/react-virtual": "3.10.8",
+    "@tanstack/react-virtual": "3.11.1",
     "downshift": "9.0.8",
     "react-aria": "^3.34.1"
   }
diff --git a/packages/eds-core-react/src/components/Tooltip/Tooltip.docs.mdx b/packages/eds-core-react/src/components/Tooltip/Tooltip.docs.mdx
index be1ca452..c8eb7edc 100644
--- a/packages/eds-core-react/src/components/Tooltip/Tooltip.docs.mdx
+++ b/packages/eds-core-react/src/components/Tooltip/Tooltip.docs.mdx
@@ -42,6 +42,9 @@ import { Tooltip } from '@equinor/eds-core-react'
 
 Keep in mind that if `Tooltip` is added to a non-focusable element, it is inaccessible to people dependent on keyboard navigation and assistive technologies.
 
+## Styling
+`Tooltip` have the classname `eds-tooltip` to make it easier to style the component globally, including tooltips built into other eds components such as `Sidebar`. Individual tooltips can otherwise be styled with `style`, `className` or `styled(Tooltip)`
+
 
 ## Examples
 
diff --git a/packages/eds-core-react/src/components/Tooltip/Tooltip.tsx b/packages/eds-core-react/src/components/Tooltip/Tooltip.tsx
index 0433e74c..2c3ad116 100644
--- a/packages/eds-core-react/src/components/Tooltip/Tooltip.tsx
+++ b/packages/eds-core-react/src/components/Tooltip/Tooltip.tsx
@@ -15,7 +15,6 @@ import {
   typographyTemplate,
   bordersTemplate,
   mergeRefs,
-  useIsomorphicLayoutEffect,
 } from '@equinor/eds-utils'
 import { tooltip as tokens } from './Tooltip.tokens'
 import {
@@ -119,6 +118,7 @@ export const Tooltip = forwardRef<HTMLDivElement, TooltipProps>(
       context,
       middlewareData: { arrow: { x: arrowX, y: arrowY } = {} },
       placement: finalPlacement,
+      elements,
     } = useFloating({
       placement,
       open,
@@ -190,11 +190,12 @@ export const Tooltip = forwardRef<HTMLDivElement, TooltipProps>(
       }),
     })
 
-    useIsomorphicLayoutEffect(() => {
-      if (shouldOpen && open) {
-        refs.floating.current?.showPopover()
+    useEffect(() => {
+      if (!elements.floating) return
+      if (elements.floating.isConnected && shouldOpen && open) {
+        elements.floating.showPopover()
       }
-    }, [open, shouldOpen, refs.floating])
+    }, [open, shouldOpen, elements.floating])
 
     const TooltipEl = (
       <StyledTooltip
@@ -202,6 +203,7 @@ export const Tooltip = forwardRef<HTMLDivElement, TooltipProps>(
         {...rest}
         {...getFloatingProps({
           ref: tooltipRef,
+          className: `eds-tooltip ${rest.className ?? ''}`,
           style: {
             ...style,
             position: strategy,
diff --git a/packages/eds-data-grid-react/package.json b/packages/eds-data-grid-react/package.json
index a474b6a4..d7a3d679 100644
--- a/packages/eds-data-grid-react/package.json
+++ b/packages/eds-data-grid-react/package.json
@@ -33,7 +33,7 @@
     "@equinor/eds-tokens": "workspace:*",
     "@equinor/eds-utils": "workspace:^",
     "@tanstack/react-table": "^8.20.1",
-    "@tanstack/react-virtual": "^3.10.8"
+    "@tanstack/react-virtual": "^3.11.1"
   },
   "devDependencies": {
     "@rollup/plugin-babel": "^6.0.4",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 367e217f..40c239ec 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -114,8 +114,8 @@ importers:
         specifier: ^3.24.1
         version: 3.24.1(react@18.3.1)
       '@tanstack/react-virtual':
-        specifier: 3.10.8
-        version: 3.10.8(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+        specifier: 3.11.1
+        version: 3.11.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
       downshift:
         specifier: 9.0.8
         version: 9.0.8(react@18.3.1)
@@ -256,8 +256,8 @@ importers:
         specifier: ^8.20.1
         version: 8.20.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
       '@tanstack/react-virtual':
-        specifier: ^3.10.8
-        version: 3.10.8(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+        specifier: ^3.11.1
+        version: 3.11.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
     devDependencies:
       '@rollup/plugin-babel':
         specifier: ^6.0.4
@@ -2859,18 +2859,18 @@ packages:
       react: '>=16.8'
       react-dom: '>=16.8'
 
-  '@tanstack/react-virtual@3.10.8':
-    resolution: {integrity: sha512-VbzbVGSsZlQktyLrP5nxE+vE1ZR+U0NFAWPbJLoG2+DKPwd2D7dVICTVIIaYlJqX1ZCEnYDbaOpmMwbsyhBoIA==}
+  '@tanstack/react-virtual@3.11.1':
+    resolution: {integrity: sha512-orn2QNe5tF6SqjucHJ6cKTKcRDe3GG7bcYqPNn72Yejj7noECdzgAyRfGt2pGDPemhYim3d1HIR/dgruCnLfUA==}
     peerDependencies:
-      react: ^16.8.0 || ^17.0.0 || ^18.0.0
-      react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0
+      react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
+      react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
 
   '@tanstack/table-core@8.20.1':
     resolution: {integrity: sha512-5Ly5TIRHnWH7vSDell9B/OVyV380qqIJVg7H7R7jU4fPEmOD4smqAX7VRflpYI09srWR8aj5OLD2Ccs1pI5mTg==}
     engines: {node: '>=12'}
 
-  '@tanstack/virtual-core@3.10.8':
-    resolution: {integrity: sha512-PBu00mtt95jbKFi6Llk9aik8bnR3tR/oQP1o3TSi+iG//+Q2RTIzCEgKkHG8BB86kxMNW6O8wku+Lmi+QFR6jA==}
+  '@tanstack/virtual-core@3.10.9':
+    resolution: {integrity: sha512-kBknKOKzmeR7lN+vSadaKWXaLS0SZZG+oqpQ/k80Q6g9REn6zRHS/ZYdrIzHnpHgy/eWs00SujveUN/GJT2qTw==}
 
   '@testing-library/dom@10.4.0':
     resolution: {integrity: sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==}
@@ -3245,6 +3245,11 @@ packages:
     engines: {node: '>=0.4.0'}
     hasBin: true
 
+  acorn@8.14.0:
+    resolution: {integrity: sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==}
+    engines: {node: '>=0.4.0'}
+    hasBin: true
+
   agent-base@6.0.2:
     resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==}
     engines: {node: '>= 6.0.0'}
@@ -9868,15 +9873,15 @@ snapshots:
       react: 18.3.1
       react-dom: 18.3.1(react@18.3.1)
 
-  '@tanstack/react-virtual@3.10.8(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+  '@tanstack/react-virtual@3.11.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
     dependencies:
-      '@tanstack/virtual-core': 3.10.8
+      '@tanstack/virtual-core': 3.10.9
       react: 18.3.1
       react-dom: 18.3.1(react@18.3.1)
 
   '@tanstack/table-core@8.20.1': {}
 
-  '@tanstack/virtual-core@3.10.8': {}
+  '@tanstack/virtual-core@3.10.9': {}
 
   '@testing-library/dom@10.4.0':
     dependencies:
@@ -10322,6 +10327,9 @@ snapshots:
 
   acorn@8.12.1: {}
 
+  acorn@8.14.0:
+    optional: true
+
   agent-base@6.0.2:
     dependencies:
       debug: 4.3.7
@@ -11384,7 +11392,7 @@ snapshots:
       debug: 4.3.5
       enhanced-resolve: 5.17.0
       eslint: 8.57.0
-      eslint-module-utils: 2.8.1(@typescript-eslint/parser@8.0.1(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@8.0.1(eslint@8.57.0)(typescript@5.5.4))(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0)
+      eslint-module-utils: 2.8.1(@typescript-eslint/parser@8.0.1(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0)
       eslint-plugin-import: 2.29.1(@typescript-eslint/parser@8.0.1(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0)
       fast-glob: 3.3.2
       get-tsconfig: 4.7.5
@@ -11396,7 +11404,7 @@ snapshots:
       - eslint-import-resolver-webpack
       - supports-color
 
-  eslint-module-utils@2.8.1(@typescript-eslint/parser@8.0.1(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@8.0.1(eslint@8.57.0)(typescript@5.5.4))(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0):
+  eslint-module-utils@2.8.1(@typescript-eslint/parser@8.0.1(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0):
     dependencies:
       debug: 3.2.7
     optionalDependencies:
@@ -11417,7 +11425,7 @@ snapshots:
       doctrine: 2.1.0
       eslint: 8.57.0
       eslint-import-resolver-node: 0.3.9
-      eslint-module-utils: 2.8.1(@typescript-eslint/parser@8.0.1(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@8.0.1(eslint@8.57.0)(typescript@5.5.4))(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0)
+      eslint-module-utils: 2.8.1(@typescript-eslint/parser@8.0.1(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0)
       hasown: 2.0.2
       is-core-module: 2.15.0
       is-glob: 4.0.3
@@ -14271,7 +14279,7 @@ snapshots:
   terser@5.34.1:
     dependencies:
       '@jridgewell/source-map': 0.3.6
-      acorn: 8.12.1
+      acorn: 8.14.0
       commander: 2.20.3
       source-map-support: 0.5.21
     optional: true


Test patch:
diff --git a/packages/eds-core-react/src/components/Tooltip/__snapshots__/Tooltip.test.tsx.snap b/packages/eds-core-react/src/components/Tooltip/__snapshots__/Tooltip.test.tsx.snap
index dc4591c6..1c5f0ce7 100644
--- a/packages/eds-core-react/src/components/Tooltip/__snapshots__/Tooltip.test.tsx.snap
+++ b/packages/eds-core-react/src/components/Tooltip/__snapshots__/Tooltip.test.tsx.snap
@@ -51,7 +51,7 @@ exports[`Tooltip Matches snapshot 1`] = `
 }
 
 <div
-  class="c0"
+  class="c0 eds-tooltip "
   id=":r0:"
   popover="manual"
   role="tooltip"