Skip to content

[BUG] Anchor element doesn't open tooltip until re-render #1189

Open
@DenisLantero

Description

@DenisLantero

Bug description
Sometimes the anchor elements don't open the tooltip, until they get rerendered.
This is the code for my anchor elements:

import React from 'react'
import PropTypes from 'prop-types'
import classNames from 'classnames'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import styles from '@contact_center/assets/stylesheets/contact_center/components/new_tickets_kanban_board/ticket/ticket_edit_action.module.scss'

const TicketEditAction = ({
  isHovering,
  ticket,
}) => {
  const cssClasses = classNames(
    styles['ticket__edit-action'],
    {
      [styles['ticket__edit-action--hover']]: isHovering,
    }
  )

  return (
    <div className={cssClasses}>
      <a
        className="btn ticket__edit-action-anchor"
        data-ticket-id={ticket.id}
      >
        <FontAwesomeIcon icon="ellipsis-vertical" />
      </a>
    </div>
  )
}

TicketEditAction.propTypes = {
  isHovering: PropTypes.bool.isRequired,
  ticket: PropTypes.object.isRequired,
}

export default TicketEditAction

And this is my code for the tooltip itself:

import React, { useState, useMemo, useCallback, useRef, useEffect } from 'react'
import styles from '@contact_center/assets/stylesheets/contact_center/components/new_tickets_kanban_board/ticket/ticket_edit_action.module.scss'

import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'

import 'react-tooltip/dist/react-tooltip.css'
import { Tooltip } from 'react-tooltip'

import { useSelector } from 'react-redux'
import { markActivitiesAsResolved, moveTicketOnTop } from '@contact_center/new_tickets_kanban_board/api/tickets'

function ActionsTooltip () {
  const [isOpen, setIsOpen] = useState(false)
  const [ticketId, setTicketId] = useState('')

  const activeAnchorRef = useRef(null)

  const {
    moveOnTopTicketUrl,
    massiveActivitiesResolveTicketUrl,
    editTicketUrl,
  } = useSelector(state => ({
    moveOnTopTicketUrl: state.base.urls.moveOnTopTicket,
    massiveActivitiesResolveTicketUrl: state.base.urls.massiveActivitiesResolveTicket,
    editTicketUrl: state.base.urls.editTicket,
  }))

  const editTicketHref = useMemo(() => editTicketUrl?.replace(':id', ticketId), [editTicketUrl, ticketId])
  const massiveActivitiesResolveTicketHref = useMemo(() => massiveActivitiesResolveTicketUrl?.replace(':id', ticketId), [massiveActivitiesResolveTicketUrl, ticketId])
  const moveOnTopTicketHref = useMemo(() => moveOnTopTicketUrl?.replace(':id', ticketId), [moveOnTopTicketUrl, ticketId])

  const onEdit = useCallback((event) => {
    event.preventDefault()
    window.open(editTicketHref, '_blank')
  }, [editTicketHref])

  const onResolveActivities = useCallback((event) => {
    event.preventDefault()
    markActivitiesAsResolved(massiveActivitiesResolveTicketHref)
  }, [massiveActivitiesResolveTicketHref])

  const onMoveOnTop = useCallback((event) => {
    event.preventDefault()
    moveTicketOnTop(moveOnTopTicketHref)
  }, [moveOnTopTicketHref])

  useEffect(() => {
    const dataTicketId = activeAnchorRef?.current?.getAttribute('data-ticket-id')
    if (dataTicketId) setTicketId(dataTicketId)
  }, [activeAnchorRef])

  return (
    <Tooltip
      className={styles['actions-tooltip']}
      id="ticket-edit-action-tooltip"
      anchorSelect=".ticket__edit-action-anchor"
      place="bottom-start"
      openOnClick={true}
      arrowColor="#ededed"
      isOpen={isOpen}
      setIsOpen={setIsOpen}
      clickable
      opacity={1}
      render={({ _, activeAnchor }) => {
        activeAnchorRef.current = activeAnchor

        return (
          <>
            <div
              className={styles['action-container']}
              onClick={(event) => {
                event.preventDefault()
                setIsOpen(false)
                onEdit(event)
              }}
            >
              <FontAwesomeIcon
                icon="pencil"
                className={styles['icon-margin-right']}
              />
              {I18n.t('frontend.contact_center.ticket.actions.edit')}
            </div>
            <div
              className={styles['action-container']}
              onClick={(event) => {
                event.preventDefault()
                setIsOpen(false)
                onResolveActivities(event)
              }}
            >
              <FontAwesomeIcon
                icon="check-double"
                className={styles['icon-margin-right']}
              />
              {I18n.t('frontend.contact_center.ticket.actions.resolve_activities')}
            </div>
            <div
              className={styles['action-container']}
              onClick={(event) => {
                event.preventDefault()
                setIsOpen(false)
                onMoveOnTop(event)
              }}
            >
              <FontAwesomeIcon
                icon="arrows-up-to-line"
                className={styles['icon-margin-right']}
              />
              {I18n.t('frontend.contact_center.ticket.actions.move_to_top')}
            </div>
          </>
        )
      }
    }
    />
  )
}

export default ActionsTooltip

Here's a video demonstrating the issue:
https://github.com/ReactTooltip/react-tooltip/assets/83024157/e89d6ff2-89ab-41c3-9c67-f39cec674870

Version of Package
v5.26.4

To Reproduce
I am not sure how you can reproduce this issue since I don't even know what's the cause of this problem

Expected behavior
The tooltip should open every time an element that respects the anchorSelect prop is clicked, regardless of the timing of its render

Desktop (please complete the following information if possible or delete this section):

  • OS: Windows 11
  • Browser: Chrome, Version 124.0.6367.119
  • React Tooltip Version: v5.26.4
  • Frameworks: React 18.2.0

Additional context
The element that you see in the video is a Drag And Drop Kanban Board with virtualized columns. Initially, I thought the problem had something to do with the virtualization of the component that contains the tooltip anchor, but the tooltips anchor work fine on elements that are not in the first render of the Kanban Board, I believe it probably has something to do with the first render of the page, but I'm not sure.
Am I doing something wrong or is there a problem with the library? Please let me know :)

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions