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

fix: Filters button tooltip is not displayed properly #54677

Merged
merged 6 commits into from
Jan 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,12 @@ const GUTTER_WIDTH = variables.gutterWidth;
* Compute the amount the tooltip needs to be horizontally shifted in order to keep it from displaying in the gutters.
*
* @param windowWidth - The width of the window.
* @param xOffset - The distance between the left edge of the window
* @param tooltipLeftEdge - The distance between the left edge of the tooltip
* and the left edge of the wrapped component.
* @param componentWidth - The width of the wrapped component.
* @param tooltipWidth - The width of the tooltip itself.
* @param [manualShiftHorizontal] - Any additional amount to manually shift the tooltip to the left or right.
* A positive value shifts it to the right,
* and a negative value shifts it to the left.
*/
const computeHorizontalShift: ComputeHorizontalShift = (windowWidth, xOffset, componentWidth, tooltipWidth, manualShiftHorizontal) => {
// First find the left and right edges of the tooltip (by default, it is centered on the component).
const componentCenter = xOffset + componentWidth / 2 + manualShiftHorizontal;
const tooltipLeftEdge = componentCenter - tooltipWidth / 2;
const tooltipRightEdge = componentCenter + tooltipWidth / 2;

const computeHorizontalShift: ComputeHorizontalShift = (windowWidth, tooltipLeftEdge, tooltipWidth) => {
const tooltipRightEdge = tooltipLeftEdge + tooltipWidth;
if (tooltipLeftEdge < GUTTER_WIDTH) {
// Tooltip is in left gutter, shift right by a multiple of four.
return roundToNearestMultipleOfFour(GUTTER_WIDTH - tooltipLeftEdge);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
type ComputeHorizontalShift = (windowWidth: number, xOffset: number, componentWidth: number, tooltipWidth: number, manualShiftHorizontal: number) => number;
type ComputeHorizontalShift = (windowWidth: number, tooltipLeftEdge: number, componentWidth: number) => number;

// eslint-disable-next-line import/prefer-default-export
export type {ComputeHorizontalShift};
42 changes: 23 additions & 19 deletions src/styles/utils/generators/TooltipStyleUtils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,18 +142,6 @@ const createTooltipStyleUtils: StyleUtilGenerator<GetTooltipStylesStyleUtil> = (
!!(tooltip && isOverlappingAtTop(tooltip, xOffset, yOffset, tooltipTargetWidth, tooltipTargetHeight)) ||
anchorAlignment.vertical === CONST.MODAL.ANCHOR_ORIGIN_VERTICAL.TOP;

// Determine if we need to shift the tooltip horizontally to prevent it
// from displaying too near to the edge of the screen.
horizontalShift = computeHorizontalShift(windowWidth, xOffset, tooltipTargetWidth, tooltipWidth, manualShiftHorizontal);

// Determine if we need to shift the pointer horizontally to prevent it from being too near to the edge of the tooltip
// We shift it to the right a bit if the tooltip is positioned on the extreme left
// and shift it to left a bit if the tooltip is positioned on the extreme right.
horizontalShiftPointer =
horizontalShift > 0
? Math.max(-horizontalShift, -(tooltipWidth / 2) + pointerWidth / 2 + variables.componentBorderRadiusSmall)
: Math.min(-horizontalShift, tooltipWidth / 2 - pointerWidth / 2 - variables.componentBorderRadiusSmall);

// Because it uses fixed positioning, the top-left corner of the tooltip is aligned
// with the top-left corner of the window by default.
// we will use yOffset to position the tooltip relative to the Wrapped Component
Expand Down Expand Up @@ -184,10 +172,9 @@ const createTooltipStyleUtils: StyleUtilGenerator<GetTooltipStylesStyleUtil> = (
// To shift the tooltip left, we'll give `left` a negative value.
//
// So we'll:
// 1) Add the horizontal shift (left or right) computed above to keep it out of the gutters.
// 2) Add the manual horizontal shift passed in as a parameter.
// 3a) Horizontally align left: No need for shifting.
// 3b) Horizontally align center:
// 1) Add the manual horizontal shift passed in as a parameter.
// 2a) Horizontally align left: No need for shifting.
// 2b) Horizontally align center:
// - Shift the tooltip right (+) to the center of the component,
// so the left edge lines up with the component center.
// - Shift it left (-) to by half the tooltip's width,
Expand All @@ -203,21 +190,38 @@ const createTooltipStyleUtils: StyleUtilGenerator<GetTooltipStylesStyleUtil> = (
// so the pointer's center lines up with the tooltipWidth's center.
// - Remove the wrapper's horizontalShift to maintain the pointer
// at the center of the hovered component.
rootWrapperLeft = xOffset + horizontalShift + manualShiftHorizontal;

rootWrapperLeft = xOffset + manualShiftHorizontal;
switch (anchorAlignment.horizontal) {
case CONST.MODAL.ANCHOR_ORIGIN_HORIZONTAL.LEFT:
pointerWrapperLeft = pointerWidth / 2;
break;
case CONST.MODAL.ANCHOR_ORIGIN_HORIZONTAL.RIGHT:
pointerWrapperLeft = horizontalShiftPointer + (tooltipWidth - pointerWidth * 1.5);
pointerWrapperLeft = tooltipWidth - pointerWidth * 1.5;
rootWrapperLeft += tooltipTargetWidth - tooltipWidth;
break;
case CONST.MODAL.ANCHOR_ORIGIN_HORIZONTAL.CENTER:
default:
pointerWrapperLeft = horizontalShiftPointer + (tooltipWidth / 2 - pointerWidth / 2);
pointerWrapperLeft = tooltipWidth / 2 - pointerWidth / 2;
rootWrapperLeft += tooltipTargetWidth / 2 - tooltipWidth / 2;
}

// Determine if we need to shift the tooltip horizontally to prevent it
// from displaying too near to the edge of the screen.
horizontalShift = computeHorizontalShift(windowWidth, rootWrapperLeft, tooltipWidth);
// Add the horizontal shift (left or right) computed above to keep it out of the gutters.
rootWrapperLeft += horizontalShift;

// Determine if we need to shift the pointer horizontally to prevent it from being too near to the edge of the tooltip
// We shift it to the right a bit if the tooltip is positioned on the extreme left
// and shift it to left a bit if the tooltip is positioned on the extreme right.
horizontalShiftPointer =
horizontalShift > 0
? Math.max(-horizontalShift, -(tooltipWidth / 2) + pointerWidth / 2 + variables.componentBorderRadiusSmall)
: Math.min(-horizontalShift, tooltipWidth / 2 - pointerWidth / 2 - variables.componentBorderRadiusSmall);

// Horizontally align left: No need for shifting.
pointerWrapperLeft += anchorAlignment.horizontal === CONST.MODAL.ANCHOR_ORIGIN_HORIZONTAL.LEFT ? 0 : horizontalShiftPointer;
pointerAdditionalStyle = shouldShowBelow ? styles.flipUpsideDown : {};

// React Native's measure() is asynchronous, we temporarily hide the tooltip until its bound is calculated
Expand Down
Loading