Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: #235 v5 Tooltip component #239

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

ksolanki7
Copy link
Contributor

Description

Demo for Tooltip Story

Screen.Recording.2024-12-06.at.6.00.18.pm.mov

@ksolanki7 ksolanki7 requested a review from kurtdoherty December 6, 2024 07:09
Copy link

Coverage summary from Codacy

See diff coverage on Codacy

Coverage variation Diff coverage
Report missing for 1e4977d1 57.89%
Coverage variation details
Coverable lines Covered lines Coverage
Common ancestor commit (1e4977d) Report Missing Report Missing Report Missing
Head commit (b8560b0) 4460 3991 89.48%

Coverage variation is the difference between the coverage for the head and common ancestor commits of the pull request branch: <coverage of head commit> - <coverage of common ancestor commit>

Diff coverage details
Coverable lines Covered lines Diff coverage
Pull request (#239) 38 22 57.89%

Diff coverage is the percentage of lines that are covered by tests out of the coverable lines that the pull request added or modified: <covered lines added or modified>/<coverable lines added or modified> * 100%

See your quality gate settings    Change summary preferences

Codacy stopped sending the deprecated coverage status on June 5th, 2024. Learn more

Footnotes

  1. Codacy didn't receive coverage data for the commit, or there was an error processing the received data. Check your integration for errors and validate that your coverage setup is correct.

@ksolanki7 ksolanki7 mentioned this pull request Dec 6, 2024
14 tasks
@ksolanki7 ksolanki7 changed the title feat: #218 v5 Tooltip component feat: #235 v5 Tooltip component Dec 6, 2024
Copy link
Contributor

@kurtdoherty kurtdoherty left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @ksolanki7 👏 This is nicely implemented. Only a few comments, the main one being whether the current API allows us to correctly wire up the a11y props.

import { render } from '@testing-library/react'
import { ToolTip } from '../index'

describe('ToolTip', () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit-pick: Tooltip is one word, not two, so I don't think Tip should be capitalised

@@ -0,0 +1,132 @@
import { styled } from '@linaria/react'

export const ElToolTipContainer = styled.div`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit-pick: Again, I don't think Tip should be capitalised; i.e. ElTooltipContainer. Looks like there's a lot of this throughout the PR.

overflow: visible;
`

export const ElToolTipChild = styled.div`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: I think this should be ElTooltip since this represents the actual presentational "tooltip" atom.

letter-spacing: var(--letter-spacing-xs);
text-align: left;
text-underline-position: from-font;
text-decoration-skip-ink: none;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: where are these underline and decoration properties coming from? Figma?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this is coming from Figma. I'll double-check with Andrei to find a solution for non-required CSS to be in a separate section if not explicitly required for elements.

}

export default meta

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: I think it would be valuable to show an additional story or two for the ElTooltip atom directly. That way it's easy to see the visual appearance of the atom without first needing to hover or focus some other element.

export interface ToolTipProps extends HTMLAttributes<HTMLDivElement> {
children: ReactNode
label?: string
tip: string
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: Figma uses description as the prop name. I think that's probably more appropriate as I'd think "tip" includes the label and the description.

onMouseLeave={() => setVisible(false)}
onFocus={() => setVisible(true)}
onBlur={() => setVisible(false)}
aria-describedby={tooltipId}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue: I'm not sure placing aria-describedby on the parent is correct. In the case where the children is a <button>, I believe the aria-describedby should be on the <button> element itself, not it's parent 🤔

I suspect we need something a little more akin to Menu.Trigger

)
}

export const ToolTipChild: FC<ToolTipChildProps> = ({ children, position, maxWidth, id }) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: is the main purpose of this component to handle maxWidth being passed in via style? The other props seem like they could just be explicitly a part of ElToolTipChild's prop interface and thus avoid the need for this extra layer?

aria-describedby={tooltipId}
>
{children}
{visible && (
Copy link
Contributor

@kurtdoherty kurtdoherty Dec 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (non-blocking): We should really be animating the tooltip in and out, so I think the visibility is best handled in CSS via a data-visible attribute.

In future, when we upgrade to React 19 (hopefully we can do this soon), we'll get access to the new Popover API, which will allow us to push the visibility into the DOM (e.g. https://codesandbox.io/p/sandbox/jp8njk)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kurtdoherty The rationale behind this approach is to address scenarios where the table contains a large number of items (e.g., 100 rows), each requiring a tooltip. Using conditional rendering ensures better performance and saves memory as we wont' load unnecessary tooltip.

I am happy to discuss and get it updated to be handled by CSS

Copy link
Contributor

@kurtdoherty kurtdoherty Dec 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using conditional rendering ensures better performance and saves memory as we wont' load unnecessary tooltip.

Have you profiled this? I only ask because I wouldn't have expected there to be much difference at the moment 🤔 If the tooltip was measuring its trigger's bounding box or something like that, then I could see there being a noticeable performance impact, but it seems like a pretty cheap element for browsers to render 🤷‍♂️

If performance does become an issue in future, there's CSS properties (e.g. content-visibility) that could potentially help us either way.

I don't mind having this go through as is. It may actually be possible we can just as easily animate the entry/exit of these DOM elements via @starting-style regardless of whether we're handling visibility in React component state or CSS (I'd forgotten about this new @-rule, though it's not supported by Firefox, so maybe animation needs to wait either way 🤷)

note: I've update my original comment to make this a non-blocking issue 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants