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

Tooltip component #27

Merged
merged 15 commits into from Nov 3, 2020
Merged

Tooltip component #27

merged 15 commits into from Nov 3, 2020

Conversation

jozefhruska
Copy link
Contributor

@jozefhruska jozefhruska commented Oct 15, 2020

TODO:

  • Documentation
  • Tests
  • Better arrow positioning?

Closes #13.

}, [])

return (
<div onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave} className={styles.container}>
Copy link
Contributor

Choose a reason for hiding this comment

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

Try setting this div's position to relative. It changes how the tooltip looks. We cannot control the parent layout and where the tooltip is going to be used. Should we try to work around it? I briefly tried strategy: fixed, but it was buggy during scrolling.

Copy link
Contributor

Choose a reason for hiding this comment

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

Should we try adding various edge cases to our stories?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

What edge cases do you have in mind?

Copy link
Contributor

Choose a reason for hiding this comment

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

Just an idea, I'm not sure how doable is it in Storybook. Could we position a tooltip to the corners so that we make sure a tooltip opens in the visible part of the screen? This is the most common problem with it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Isn't this just re-testing of something that Popper.js has already covered?

@aigoncharov
Copy link
Contributor

aigoncharov commented Oct 16, 2020

Guys, rc-trigger goes above and beyond to get the underlying ref from children (see https://github.com/react-component/trigger/blob/master/src/index.tsx). I would be against excessive wrapping as it complicates the layout with some hidden components.
How would you feel if used a render prop instead?

<Tooltip>
  (triggerRef) => <Button ref={trigger} />
</Tooltip>

It is not that elegant, but it significantly simplifies the code and removes the need for extra layout.

To mitigate the disabled button issue if we see it in our stories, we could not really disable the button, but just make it look disabled.

@danad02
Copy link
Contributor

danad02 commented Oct 16, 2020

@aigoncharov I don't mind using a render props as a solution. As long as it simplifies the layout I'm in.

To mitigate the disabled button issue if we see it in our stories, we could not really disable the button, but just make it look disabled.

But I don't like this, it seems like we would start bending the rules set by standard. I would rather wrap disabled buttons and add a comment.

@jozefhruska
Copy link
Contributor Author

Guys, rc-trigger goes above and beyond to get the underlying ref from children (see https://github.com/react-component/trigger/blob/master/src/index.tsx). I would be against excessive wrapping as it complicates the layout with some hidden components.
How would you feel if used a render prop instead?

<Tooltip>
  (triggerRef) => <Button ref={trigger} />
</Tooltip>

It is not that elegant, but it significantly simplifies the code and removes the need for extra layout.

To mitigate the disabled button issue if we see it in our stories, we could not really disable the button, but just make it look disabled.

Actually this was my first implementation of this Tooltip, but then I though you won't like this approach. I'm all for it! ❤️ Or maybe we can support both cases?

@jozefhruska jozefhruska force-pushed the feat/tooltip branch 3 times, most recently from 5bd532e to 0c28756 Compare October 19, 2020 16:03
@@ -10,11 +10,13 @@ beforeEach(() => {
jest.spyOn(console, 'error').mockImplementation((...args) => {
isConsoleErrorOrWarning = true
originalError(...args)
console.log('ERROR', ...args)
Copy link
Contributor

Choose a reason for hiding this comment

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

Why do we need it? We already do console.error and console.warn via originalError and originalWarn?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Indeed, this shouldn't be there, good catch!

.wrapper {
max-width: c.$tooltipMaxWidth;
word-wrap: break-word;
.tooltip-sr {
Copy link
Contributor

Choose a reason for hiding this comment

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

For consistency with other stylesheets

Suggested change
.tooltip-sr {
.tooltipSr {

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated manually 👍

background: c.$colorNeutralLighter;
border: c.$borderWidth solid c.$colorNeutralLight;
border-radius: c.$borderRadius;
font-size: inherit;
Copy link
Contributor

Choose a reason for hiding this comment

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

Why do you think we need to inherit the font-size? I figured it would be the same for all tooltips

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You're right, I don't know what I was thinking 🤷‍♂️ Removed 👍

className={cn(styles.container, className, {
[styles.padding]: padding === 'default',
})}
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.

nit: Should we move it to the Icon? I feel like we are describing the icon actually

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hmm, I'm not sure, but probably it makes more sense on icon. Updated 👍

)

Button.displayName = 'Button'
Copy link
Contributor

Choose a reason for hiding this comment

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

Why do we need this one?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ESLint requires explicit displayName when using forwardRef.

@@ -44,10 +46,11 @@ export type ButtonAccessibleIconRightProps =
}

export type ButtonDisabledProps =
| ({ disabledTooltip: string } & Required<Pick<ButtonHTMLAttributes<HTMLButtonElement>, 'disabled'>>)
| ({ disabledTooltip: string; disabledTooltipId: string } & Required<Pick<ButtonHTMLAttributes<HTMLButtonElement>, 'disabled'>>)
Copy link
Contributor

Choose a reason for hiding this comment

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

Why do we need to pass it? Couldn't we always generate it internally?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think we can, removed 👍

[styles.secondary]: kind === 'secondary',
[styles.transparent]: kind === 'transparent',
})}
disabled={disabled}
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we add aria-describedby here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Indeed, good catch, added 👍

helperText: 'A long time ago in a galaxy far, far away....',
className: styles.helperText,
// This has to be wrapper in act() - you can find an explanation in Tooltip test file.
await act(async () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Does it still have to be wrapped in act? I thought mountAndCheckA11Y now does that automatically

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It does not, it's just a leftover when mountAndCheckA11Y didn't do it automatically. Removed 👍

packages/ui/src/Tooltip.tsx Outdated Show resolved Hide resolved

&::after {
border-top: c.$tooltipArrowSize solid c.$colorNeutralLighter;
transform: translateY(-2px);
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
transform: translateY(-2px);
transform: translateY(-(c.$tooltipArrowSize / 3));


&::after {
border-right: c.$tooltipArrowSize solid c.$colorNeutralLighter;
transform: translateX(-4px);
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
transform: translateX(-4px);
transform: translateX(-(c.$tooltipArrowSize / 3 * 2));


&::after {
border-bottom: c.$tooltipArrowSize solid c.$colorNeutralLighter;
transform: translateY(-4px);
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
transform: translateY(-4px);
transform: translateY(-(c.$tooltipArrowSize / 3 * 2));


&::after {
border-left: c.$tooltipArrowSize solid c.$colorNeutralLighter;
transform: translateX(-2px);
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
transform: translateX(-2px);
transform: translateX(-(c.$tooltipArrowSize / 3));

Copy link
Contributor

@aigoncharov aigoncharov left a comment

Choose a reason for hiding this comment

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

Great job! Love how it looks in the end!

}

export const AutoPlacement = () => (
<div className={utilStyles.wrapperCentered}>
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we add more padding so the screenshots are not cropped?

expect(tooltip.exists()).toBeTruthy()
expect(tooltip.props()).toEqual(expectedProps)
expect(tooltip.exists(Child)).toBeTruthy()
expect(wrapper.findDataTest('tooltip-overlay').hasClass('hidden')).toBeFalsy()
Copy link
Contributor

Choose a reason for hiding this comment

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

nit

Suggested change
expect(wrapper.findDataTest('tooltip-overlay').hasClass('hidden')).toBeFalsy()
expect(wrapper.findDataTest('tooltip-overlay').hasClass(styles.hidden)).toBeFalsy()

const Child = () => <div />
expect(wrapper.findDataTest('tooltip-reference').exists()).toBeTruthy()
expect(tooltipOverlay.exists()).toBeTruthy()
expect(tooltipOverlay.text()).toEqual('Tooltip content')

Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
expect(tooltipOverlay.hasClass(styles.hidden)).toBeTruthy()

Copy link
Contributor

@danad02 danad02 left a comment

Choose a reason for hiding this comment

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

LGTM. Great job 👏

@aigoncharov aigoncharov merged commit f3fb876 into master Nov 3, 2020
@aigoncharov aigoncharov deleted the feat/tooltip branch November 3, 2020 07:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[UI core library] Tooltip
6 participants