adobe / react-spectrum

A collection of libraries and tools that help you build adaptive, accessible, and robust user experiences.
https://react-spectrum.adobe.com
Apache License 2.0
12.15k stars 1.06k forks source link

`react-aria-components/Tooltip`: `state.placement` should receive full `Placement` instead of `PlacementAxis` #6517

Open unional opened 4 weeks ago

unional commented 4 weeks ago

Provide a general summary of the feature here

Currently the state.placement in className or style callback is a PlacementAxis, which only contains top | bottom | left | right.

When the position of the tooltip needs to adjust, it may also need to flip.

e.g. a button at the top-left corner with a tooltip placement='top end' should flip on both axis to bottom start.

Currently we only get bottom which does not provide enough information to adjust the css accordingly.

image

๐Ÿค” Expected Behavior?

state.placement contain full Placement information.

๐Ÿ˜ฏ Current Behavior

state.placement only contains PlacementAxis values.

By the way, do you know in what case state.placement will contain the value center?

๐Ÿ’ Possible Solution

No response

๐Ÿ”ฆ Context

The solution is not complete.

๐Ÿ’ป Examples

No response

๐Ÿงข Your Company/Team

Palo Alto Networks

๐Ÿ•ท Tracking Issue

No response

unional commented 4 weeks ago

Example for all 4 corners: image

Note that related to #6505, I have isOpen but it is not rendered in this case because the positions are off screen.

unional commented 4 weeks ago

One more thing I notice is state.placement can be undefined. This happens when it is first created and also when isOpen changes.

image

But the type didn't mention that.

export interface TooltipRenderProps {
    /**
     * The placement of the tooltip relative to the trigger.
     * @selector [data-placement="left | right | top | bottom"]
     */
    placement: PlacementAxis;
snowystinger commented 3 weeks ago

Would you mind providing a reproduction of this to discuss more?

unional commented 2 weeks ago

While I try to create a repo, I notice that in the other example you share here: https://github.com/adobe/react-spectrum/blob/6e57855257f54738418f98c37efae798bf9fb4ad/packages/react-aria-components/stories/Tooltip.stories.tsx#L116

It is "working" in that example because the offset and the svg are hardcoded:

<Tooltip
  shouldFlip={false}
  offset={7}
  arrowBoundaryOffset={leftTop}
  style={{...}}
  >
  <OverlayArrow>
    <svg style={{...transform: 'rotate(-90deg)'...}} />
  </OverlayArrow>
</Tooltip>

if you try to define a reusable styled component, it wouldn't work:

<Tooltip
  style={(state) => {
    // no `shouldFlip`, and on which axis or both axis
    // `state.placement` no `top start` (as in OP)
    // thus no way to determine `offset` either
  }
  >
  <OverlayArrow>
    <svg style={{ ... no way to determine how to transform ... }}/>
  </OverlayArrow>
</Tooltip>

UPDATE: for children, you can:

<Tooltip>
  {({ placement }) => (
    <OverlayArrow>
      <svg style={{ transform: placement === 'left' ? ... : ... }}/>
    </OverlayArrow>
  )}
</Tooltip>

It works because that transform only needs the 4 directions.