From 373a93f9c39c93e74deafc2298ee84ca85193fa2 Mon Sep 17 00:00:00 2001 From: Hetu Nandu Date: Mon, 1 May 2023 14:32:16 +0530 Subject: [PATCH] fix: Scroll to selected widget failing when it's a container (#22777) ## Description Fixes the scenario where the selected widget was not getting scrolled to on page change. When the selected widget was a container, it was not getting scrolled. This will update the scenarios where the page will scroll to the selected "container" widget > Fix the bug where the selected container widget was not in view Fixes #22099 Media https://user-images.githubusercontent.com/12022471/234842826-bae5388f-7813-441e-814b-7669179e211d.mov ## Type of change - Bug fix (non-breaking change which fixes an issue) ## How Has This Been Tested? - Manual ### Test Plan > Add Testsmith test cases links that relate to this PR ### Issues raised during DP testing > Link issues raised during DP testing for better visiblity and tracking (copy link from comments dropped on this PR) ## Checklist: ### Dev activity - [ ] My code follows the style guidelines of this project - [ ] I have performed a self-review of my own code - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [ ] My changes generate no new warnings - [ ] I have added tests that prove my fix is effective or that my feature works - [ ] New and existing unit tests pass locally with my changes - [ ] PR is being merged under a feature flag ### QA activity: - [ ] Test plan has been approved by relevant developers - [ ] Test plan has been peer reviewed by QA - [ ] Cypress test cases have been added and approved by either SDET or manual QA - [ ] Organized project review call with relevant stakeholders after Round 1/2 of QA - [ ] Added Test Plan Approved label after reveiwing all Cypress test --- app/client/src/utils/helpers.tsx | 53 +++++++++++++++++++++++--------- 1 file changed, 38 insertions(+), 15 deletions(-) diff --git a/app/client/src/utils/helpers.tsx b/app/client/src/utils/helpers.tsx index 2382bf4acb..d1e8e2b728 100644 --- a/app/client/src/utils/helpers.tsx +++ b/app/client/src/utils/helpers.tsx @@ -36,6 +36,7 @@ import { checkContainerScrollable } from "widgets/WidgetUtils"; import type { ContainerWidgetProps } from "widgets/ContainerWidget/widget"; import type { WidgetProps } from "widgets/BaseWidget"; import { getContainerIdForCanvas } from "sagas/WidgetOperationUtils"; +import scrollIntoView from "scroll-into-view-if-needed"; export const snapToGrid = ( columnWidth: number, @@ -237,7 +238,7 @@ export const quickScrollToWidget = ( if (el && canvas && !isElementVisibleInContainer(el, canvas)) { const scrollElement = getWidgetElementToScroll(widgetId, canvasWidgets); if (scrollElement) { - scrollElement.scrollIntoView({ + scrollIntoView(scrollElement, { block: "center", inline: "nearest", behavior: "smooth", @@ -247,24 +248,46 @@ export const quickScrollToWidget = ( }); }; -// Checks if the element in a container is visible or not. -// Can be used to decide if scroll is needed +/** Checks if a percentage of element is visible inside a container or not + + The function first retrieves the bounding rectangles of both the + container and the element using the getBoundingClientRect() method. + It then calculates the visible area of the element inside the container + by determining the intersection between the two bounding rectangles. + + The function then calculates the percentage of the element that is + visible by dividing the visible area by the total area of the element + and multiplying by 100. Finally, it returns true if the visible percentage + is greater than or equal to the desired percentage, and false otherwise. + + Note that this function assumes that the element and the container + are both positioned using the CSS position property, and that the + container is positioned relative to its containing block. If the + element or the container have a different positioning, the + function may need to be adjusted accordingly. + **/ function isElementVisibleInContainer( element: HTMLElement, container: HTMLElement, + percentage = 100, ) { - const elementRect = element.getBoundingClientRect(); - const containerRect = container.getBoundingClientRect(); - return ( - ((elementRect.top > containerRect.top && - elementRect.top < containerRect.bottom) || - (elementRect.bottom < containerRect.bottom && - elementRect.bottom > containerRect.top)) && - ((elementRect.left > containerRect.left && - elementRect.left < containerRect.right) || - (elementRect.right < containerRect.right && - elementRect.right > containerRect.left)) - ); + const elementBounds = element.getBoundingClientRect(); + const containerBounds = container.getBoundingClientRect(); + // Calculate the visible area of the element inside the container + const visibleWidth = + Math.min(elementBounds.right, containerBounds.right) - + Math.max(elementBounds.left, containerBounds.left); + const visibleHeight = + Math.min(elementBounds.bottom, containerBounds.bottom) - + Math.max(elementBounds.top, containerBounds.top); + const visibleArea = visibleWidth * visibleHeight; + + // Calculate the percentage of the element that is visible + const elementArea = element.clientWidth * element.clientHeight; + const visiblePercentage = (visibleArea / elementArea) * 100; + + // Return whether the visible percentage is greater than or equal to the desired percentage + return visiblePercentage >= percentage; } function getWidgetElementToScroll(