-
Notifications
You must be signed in to change notification settings - Fork 683
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
SwatchTooltip component #956
Conversation
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.
Had a look at the implementation. The left and right padding around the label needs to be reduced, and the vertical padding increased. On second thought, off-center tip makes the tooltip look unbalanced.
Would centering the tip cause any issues with display when the tooltip needs to appear on the swatch at the left edge of the screen?
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.
Confirmed that this looks great in:
- Chrome
- Safari
- Firefox
- Edge
- iOS Simulator
- Android Emulator
One little prop type issue and then this is good to merge.
...ages/venia-concept/src/components/ProductOptions/__tests__/__snapshots__/option.spec.js.snap
Outdated
Show resolved
Hide resolved
Totally agree.
It would, yeah. Would you mind if we merged this now and I create a follow up ticket to address these concerns? |
@supernova-at Sure, as long as we fix the issues I'm fine with changes being addressed in a follow-up ticket. I changed the status to "approved" for my review. |
@soumya-ashok Awesome - created #1024 for follow up. |
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.
This looks good, but I think we have an opportunity for an a11y win here. Below are some basic guidelines for tooltips from WAI-ARIA.
- The tooltip never receives focus. Focus stays on the textbox.
- The tooltip widget can shown via keyboard focus or by the onmouse event.
- The tooltip widget can be hidden by removing focus from the text box or by moving the mouse off the textbox.
- The tooltip widget can be hidden by pressing the Escape key
- The tooltip is only hidden via JavaScript and CSS selectors. If JavaScript is not available the tooltip is shown.
- The element that serves as the tooltip container has role
tooltip
. - The element that triggers the tooltip references the tooltip element with
aria-describedby
.
Any chance I could convince you to allow this in the followup ticket? 😄 |
I don't think it's that much work to add. |
Agreed on all points. |
In progress....
|
This pull request is automatically deployed with Now. |
}; | ||
|
||
onKeyDown = event => { | ||
if (event.key === 'Escape') { |
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.
if (event.key === 'Escape') { | |
if (event.key === 'Escape' || event.key === 'Tab') { |
This would also hide it if you are moused in and then press tab. This could present an issue wherein there are focusable children within the button, imagine some text within the swatch, and pressing Tab
should move focus to the text and keep the tooltip above the swatch.
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.
This suggestion would help solve the problem of multiple tooltips showing at the same time. This occurs when one Swatch has focus and another is being moused over.
But it may not be worth the effort.
- We'd have to add logic to
SwatchTooltip
to workaround the new issue that it would present, which would be duplicating a lot of whatblur
is supposed to tell us. - Since this isn't a form, users usually aren't navigating with keyboard and mouse.
We could add some sort of TooltipController
component that ensures that only one tooltip is showing at a time, but that seems like overkill too.
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 agree, it's not worth the effort. The intentions are good here—accessibility is important—but reimplementing keyboard navigation is generally a sign that we're using the wrong elements in the first place.
Rather than a list of <button>
elements, product options (including swatches) should really be radio buttons, in part because this really is a form. The native mechanisms browsers have for navigating forms are actually really comprehensive, and we should be using them.
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.
Generally speaking, if the expected behavior is that only one tooltip can be open at a time, then it's not local state: it's shared state. So it sounds like this situation does call for a "controller". Context is good for this purpose.
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.
At my last company we had a FocusManager
component that handled this sort of thing. Probably a bit overkill for now.
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.
@jimbo great points all around.
if the expected behavior is that only one tooltip can be open at a time
This is the piece I'm iffy about. I mean, it sounds right but it is also a pretty rare occurrence so I lean towards "out of scope" here. When this thing makes it into Peregrine we can definitely generalize and make improvements to it.
What do you think?
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.
When this thing makes it into Peregrine we can definitely generalize and make improvements to it.
Yeah, that's probably the right approach.
…in the SwatchTooltip component. - Also updates affected snapshots
…o into supernova/700-swatch_tooltips
PR Updated:
|
}; | ||
|
||
onKeyDown = event => { | ||
if (event.key === 'Escape') { |
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 agree, it's not worth the effort. The intentions are good here—accessibility is important—but reimplementing keyboard navigation is generally a sign that we're using the wrong elements in the first place.
Rather than a list of <button>
elements, product options (including swatches) should really be radio buttons, in part because this really is a form. The native mechanisms browsers have for navigating forms are actually really comprehensive, and we should be using them.
onMouseLeave: over([ | ||
child.props.onMouseLeave, | ||
this.onMouseLeave | ||
]) |
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've never seen this pattern before. Ordinarily, you would call the props callback from the class handler. Any reason we shouldn't do that here?
Also, by convention, class handlers are named handleEvent
rather than onEvent
.
class Foo extends Component {
handleClick = event => {
const { id, onClick } = this.props
// this component's business
event.preventDefault()
// its parent's business
// note: event object is treated as private
// callback gets only what it needs
if (typeof onClick === "function") {
onClick(id)
}
}
render() {
const { handleClick } = this
return <button onClick={handleClick} />
}
}
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 that's a good call - the reason this particular case is different is because this SwatchTooltip
component is the parent, not the child.
In other words:
<SwatchTooltip>
<Swatch />
</SwatchTooltip>
So for a given event handler - let's say onClick
- SwatchTooltip
(the parent) wants its handler executed while also executing the Swatch
(child)'s handler.
I suppose I could do something like
onMouseOver = () => {
// parent business.
this.setState({ isShowing: true });
// child business.
const child = this.getChild(); // some logic that uses React.Children to get the right one
if (child.props.onMouseOver) {
child.props.onMouseOver();
}
};
and repeat that pattern for each event handler.
I'm mostly just trying to avoid tightly coupling these components.
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 mostly just trying to avoid tightly coupling these components.
Why's that? It seems to me that the tooltip should be a child of the Swatch
, rendered by Swatch
, and pretty coupled to 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.
Why's that? It seems to me that the tooltip should be a child of the Swatch, rendered by Swatch, and pretty coupled to it.
Good point, that would definitely make things much simpler here. In the future we may want a generic Tooltip
component like this, but that's out of scope here.
}; | ||
|
||
onKeyDown = event => { | ||
if (event.key === 'Escape') { |
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.
Generally speaking, if the expected behavior is that only one tooltip can be open at a time, then it's not local state: it's shared state. So it sounds like this situation does call for a "controller". Context is good for this purpose.
} | ||
|
||
/* The tooltip triangle that points down. */ | ||
.tooltip:before { |
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.
Love me some pseudo-element triangles.
We're going to merge this with the caveat that we try to figure out how to invert the parent-child relationship of the ToolTip component. |
…ore Peregrine refactor
Description
This PR adds a new
SwatchTooltip
component and uses it in theProductOptions
views (product page and edit mini cart item).It updates the closed #712.
Related Issue
Closes #700 .
Motivation and Context
There was a UAT ticket for providing these tooltips.
How Has This Been Tested?
yarn test
and manually on the product pages (PDPs) and in the mini-cart edit item dialog.Screenshots (if appropriate):
Proposed Labels for Change Type/Package
FEATURE
venia-concept
Checklist: