Browse Source

Maintenance: Desktop view - Tooltip text gets selected in addition to the trigger text when double clicking

Benjamin Scharf 9 months ago
parent
commit
d3c4015d2e

+ 17 - 17
app/frontend/apps/desktop/plugins/directives/__tests__/tooltip.spec.ts

@@ -11,15 +11,15 @@ describe('TooltipDirective', () => {
     it('should show/hide tooltip on hover', async () => {
       const wrapper = renderComponent({
         template: `
-        <div v-tooltip="'Hello, Tooltip'">Foo Test World</div>
-      `,
+          <div v-tooltip="'Hello, Tooltip'">Foo Test World</div>
+         `,
       })
 
       await wrapper.events.hover(wrapper.getByText('Foo Test World'))
 
-      await waitFor(() => {
-        expect(wrapper.queryByText('Hello, Tooltip')).toBeInTheDocument()
-      })
+      await waitFor(() =>
+        expect(wrapper.queryByText('Hello, Tooltip')).toBeInTheDocument(),
+      )
 
       await wrapper.events.unhover(wrapper.getByText('Foo Test World'))
 
@@ -34,9 +34,9 @@ describe('TooltipDirective', () => {
         <div v-tooltip="'Hello, Tooltip'">Foo Test World</div>
       `,
       })
-      await waitFor(() => {
-        expect(wrapper.queryByLabelText('Hello, Tooltip')).toBeInTheDocument()
-      })
+      await waitFor(() =>
+        expect(wrapper.queryByLabelText('Hello, Tooltip')).toBeInTheDocument(),
+      )
     })
 
     it('should hide tooltip on scroll', async () => {
@@ -48,15 +48,15 @@ describe('TooltipDirective', () => {
 
       await wrapper.events.hover(wrapper.getByText('Foo Test World'))
 
-      await waitFor(() => {
-        expect(wrapper.queryByText('Hello, Tooltip')).toBeInTheDocument()
-      })
+      await waitFor(() =>
+        expect(wrapper.queryByText('Hello, Tooltip')).toBeInTheDocument(),
+      )
 
       window.dispatchEvent(new Event('scroll'))
 
-      await waitFor(() => {
-        expect(wrapper.queryByText('Hello, Tooltip')).not.toBeInTheDocument()
-      })
+      await waitFor(() =>
+        expect(wrapper.queryByText('Hello, Tooltip')).not.toBeInTheDocument(),
+      )
     })
   })
 
@@ -85,9 +85,9 @@ describe('TooltipDirective', () => {
       await fireEvent.touchStart(wrapper.getByText('Foo Test World'))
       await fireEvent.touchEnd(wrapper.getByText('Foo Test World'))
 
-      await waitFor(() => {
-        expect(wrapper.queryByText('Hello, Tooltip')).not.toBeInTheDocument()
-      })
+      await waitFor(() =>
+        expect(wrapper.queryByText('Hello, Tooltip')).not.toBeInTheDocument(),
+      )
     })
 
     it('updated tooltip locale', async () => {

+ 14 - 5
app/frontend/apps/desktop/plugins/directives/tooltip.ts

@@ -59,7 +59,7 @@ const createTooltip = (
 ) => {
   const tooltipNode = document.createElement('div')
   tooltipNode.classList.add('tooltip')
-  tooltipNode.style.position = 'fixed'
+
   tooltipNode.style.top = top
   tooltipNode.style.left = left
   tooltipNode.setAttribute('aria-hidden', 'true')
@@ -137,7 +137,7 @@ const addTooltip = (
   tooltipNode.style.top = top
   tooltipNode.style.left = left
 
-  targetNode.insertAdjacentElement('afterend', tooltipNode)
+  document.body.insertAdjacentElement('beforeend', tooltipNode)
 
   setTimeout(() => {
     tooltipNode.classList.add('tooltip-animate')
@@ -268,10 +268,19 @@ export default {
       }
     },
     updated(element: HTMLDivElement, { value: message }) {
-      element.setAttribute('aria-label', message)
+      // In some cases we update the aria-label on an interval f.e table time cells
+      // We don't want to write to the DOM on every update if nothing has changed
+      if (element.getAttribute('aria-label') !== message)
+        element.setAttribute('aria-label', message)
     },
-    beforeUnmount() {
-      // Cleanup
+    beforeUnmount(element) {
+      // If we dynamically remove the element from the DOM, we need to remove it from the tooltipTargetRecords
+      tooltipTargetRecords = tooltipTargetRecords.filter(
+        (record) => record.element !== element,
+      )
+      // If there are no more elements with the tooltip directive, remove event listeners
+      if (tooltipTargetRecords.length !== 1) return
+      // Cleanup only on the last element
       if (isTooltipInDom) removeTooltips()
       if (isListeningToEvents) cleanupEventHandlers()
       isListeningToEvents = false

+ 1 - 1
app/frontend/apps/desktop/styles/main.css

@@ -79,7 +79,7 @@
   */
 
   .tooltip {
-    @apply w-fit -translate-y-2 text-wrap rounded-md border border-neutral-100 bg-blue-200 px-2 py-1 text-xs leading-snug text-gray-100 opacity-0 transition-all dark:border-gray-900 dark:bg-gray-700 dark:text-neutral-400;
+    @apply fixed w-fit -translate-y-2 select-none text-wrap rounded-md border border-neutral-100 bg-blue-200 px-2 py-1 text-xs leading-snug text-gray-100 opacity-0 transition-all dark:border-gray-900 dark:bg-gray-700 dark:text-neutral-400;
 
     &-animate {
       @apply translate-y-0 opacity-100;