-
Notifications
You must be signed in to change notification settings - Fork 1k
refactor: replace Popover with Tooltip in HelpTooltip #19635
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
Conversation
AgentOutdatedTooltip
IdpOrgSyncPageView, TableColumnHelpTooltip, TemplateInsightsPage
LegacyGroupSyncHeader
Before I jump into review it, could you please fix the CI issues? So we can properly QA this. |
OrganizationBreadcrumb
This reverts commit c93e092.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Everything looks pretty good to me. I had a few small nits, but nothing worth blocking over
Just let me know if you have any questions about my feedback
import { | ||
HelpTooltip, | ||
HelpTooltipContent, | ||
HelpTooltipText, | ||
HelpTooltipTitle, | ||
} from "components/HelpTooltip/HelpTooltip"; | ||
import { Stack } from "components/Stack/Stack"; | ||
import { TooltipTrigger } from "components/Tooltip/Tooltip"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Stuff like this is making me worry we're not closing the loop on the abstraction all the way
I think my preference would be to have HelpTooltip
export a separate HelpTooltipTrigger
component, so that in the future, people don't need to go rifling around for the right component to get the help tooltip wired up. We could even make it so that HelpTooltip
just exports TooltipTrigger
under a different name – but I think that co-locating everything you need to wire up a HelpTooltip
in one file is really important
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The tricky thing is that the HelpTooltipTrigger
component already exported by HelpTooltip
renders a button with an SVG icon:
export const HelpTooltipTrigger = forwardRef< |
which is currently instantiated in 16 places like this:
<HelpTooltipTrigger size="small" /> |
So my thought with using TooltipTrigger
here is that you can insert whatever elements you want to act as a trigger (like in AgentLatency
we're using a span instead of a button). Looking at it again, it is clunky.
What do you think about renaming the existing HelpTooltipTrigger
to something like HelpTooltipIcon
or HelpTooltipIconTrigger
, so that we can export Radix's TooltipTrigger
as HelpTooltipTrigger
like you suggested?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I like the renaming approach better. I'm not even fully sure about having a version of the trigger that has an icon pre-baked, but I don't think it's all that egregious, and I imagine it'd be pretty easy to change it down the line
@@ -3,18 +3,17 @@ import { | |||
css, | |||
type Interpolation, | |||
type Theme, | |||
useTheme, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🙏
expect(screen.getByRole("tooltip")).toHaveTextContent( | ||
meta.args.message, | ||
), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Big fan of the more accessible selectors
onClick={() => { | ||
onUpdate(); | ||
// TODO can we move this tooltip-closing logic to the definition of HelpTooltipAction? | ||
setIsOpen(false); | ||
}} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm trying to get some clarity on this comment: was this meant more in the sense of "I'm not sure if it's a good idea to do this", or "I feel like this is a good idea, but I'm not 100% sure how to do it"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A bit of both, but more the latter. I think whenever a HelpTooltipAction
is clicked, we want to close the tooltip. By having the tooltip-closing logic built into HelpTooltipAction
by default, we could write handlers like onClick={onUpdate}
here + wherever else we want to execute a function when closing a tooltip.
Since Radix doesn't export a component like <Popover.Close />
, it seems the only way to do this is with a state hook. Is it a good idea to make every tooltip a controlled component? I'm not sure
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, looking at Radix's API docs, I don't see anything that gives direct access to the state that's being contained inside Popover.Root
I imagine that if we want to bake that behavior in, we'd basically need to make wrappers over all the Popover
components, and then wire up our own custom context (on top of the one already used by Radix) to control the closing state. I don't think that's too bad, but I also feel like Radix could've easily given a way to trigger that behavior if they felt like it was a common enough usage pattern
Unless we have a bunch of other components wiring that behavior up already, I feel like we can leave things be and wait for more examples to emerge
site/src/modules/workspaces/WorkspaceOutdatedTooltip/WorkspaceOutdatedTooltip.tsx
Outdated
Show resolved
Hide resolved
site/src/pages/TemplateVersionEditorPage/PublishTemplateVersionDialog.tsx
Outdated
Show resolved
Hide resolved
export const HelpTooltip: FC<TooltipProps> = (props) => { | ||
return ( | ||
<TooltipProvider> | ||
<Tooltip delayDuration={0} {...props} /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think 0 is probably too fast. what's the default here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The default is 700 which feels very long.
Worth mentioning that the MUI popover, which deprecated/Popover
uses, doesn't use any delay, and I don't think we've added any:
coder/site/src/components/deprecated/Popover/Popover.tsx
Lines 130 to 132 in 2030907
const hoverProps = { | |
onPointerEnter: (event: PointerEvent<HTMLElement>) => { | |
popover.setOpen(true); |
so I used a delay of 0 to keep consistency with our current UX
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could we set it to like, 200? I feel like 0 is intense
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, 0 is exactly as intense as prod is rn:
Screen.Recording.2025-09-04.at.4.05.34.PM.mov
I'm so used to 0 delay that 200 feels sluggish to me:
for #19397
Currently there are 24 files that import bindings from the deprecated
Popover
component. One of those isHelpTooltip
, which is instantiated in 24 other files. After this PR, the remaining files that import the deprecatedPopover
should be able to be migrated in just 1-2 more PRs. 🤞🏽I opted for
Tooltip
as a replacement because it's triggered on hover, unlike our newPopover
which is triggered on click.