Fix feed navigation shortcuts when first article is not 100% visible (#11874)
Co-authored-by: Nick Taylor <nick@iamdeveloper.com> Co-authored-by: Hariharan <hariharan.s@samsung.com>
This commit is contained in:
parent
956caf69c7
commit
208d788672
2 changed files with 48 additions and 13 deletions
|
|
@ -152,7 +152,7 @@ function navigate(
|
|||
const nextFocusable = nextContainer?.querySelector(focusableSelector);
|
||||
if (nextFocusable) {
|
||||
nextFocusable.focus();
|
||||
if (!isInViewport(nextFocusable, 64)) {
|
||||
if (!isInViewport({ element: nextFocusable, offsetTop: 64 })) {
|
||||
window.scrollTo({ top: nextContainer.offsetTop - 64 });
|
||||
}
|
||||
}
|
||||
|
|
@ -211,15 +211,27 @@ function getPreviousElement(
|
|||
}
|
||||
|
||||
/**
|
||||
* Gets the first visible element that matches a selector
|
||||
* Checks if the first completely visible element is present that matches a selector and returns if it is available
|
||||
* If that isn't visible, it looks for the partially visible element that is present and returns that
|
||||
* If no elements visible(like the banner case which could cover the entire viewport), we select the first element from the list
|
||||
*
|
||||
* @param {string} selector - The CSS selector
|
||||
*
|
||||
* @returns {object} The first visible element
|
||||
*/
|
||||
function getFirstVisibleElement(selector) {
|
||||
const elements = document.querySelectorAll(selector);
|
||||
return Array.prototype.find.call(elements, (element) =>
|
||||
isInViewport(element),
|
||||
const elements = [...document.querySelectorAll(selector)];
|
||||
const completelyVisibleFirstElement = elements.find((element) =>
|
||||
isInViewport({ element }),
|
||||
);
|
||||
if (completelyVisibleFirstElement) {
|
||||
return completelyVisibleFirstElement;
|
||||
}
|
||||
const partiallyVisibleFirstElement = elements.find((element) =>
|
||||
isInViewport({ element, allowPartialVisibility: true }),
|
||||
);
|
||||
if (partiallyVisibleFirstElement) {
|
||||
return partiallyVisibleFirstElement;
|
||||
}
|
||||
return elements[0];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,22 +3,45 @@
|
|||
*
|
||||
* @example
|
||||
* const element = document.getElementById('element');
|
||||
* isInViewport(element); // true or false
|
||||
* isInViewport({element, allowPartialVisibility = true}); // true or false
|
||||
*
|
||||
* @param {object} element - The HTML element to check
|
||||
* @param {HTMLElement} element - The HTML element to check
|
||||
* @param {number} [offsetTop=0] - Part of the screen to ignore counting from the top
|
||||
*
|
||||
* @param {boolean} [allowPartialVisibility=false] - A boolean to flip the check between partial or completely visible in the viewport
|
||||
* @returns {boolean} isInViewport - true if the element is visible in the viewport
|
||||
*/
|
||||
export function isInViewport(element, offsetTop = 0) {
|
||||
export function isInViewport({
|
||||
element,
|
||||
offsetTop = 0,
|
||||
allowPartialVisibility = false,
|
||||
}) {
|
||||
const boundingRect = element.getBoundingClientRect();
|
||||
const clientHeight =
|
||||
window.innerHeight || document.documentElement.clientHeight;
|
||||
const clientWidth = window.innerWidth || document.documentElement.clientWidth;
|
||||
const topIsInViewport =
|
||||
boundingRect.top <= clientHeight && boundingRect.top >= offsetTop;
|
||||
const rightIsInViewport =
|
||||
boundingRect.right >= 0 && boundingRect.right <= clientWidth;
|
||||
const bottomIsInViewport =
|
||||
boundingRect.bottom >= offsetTop && boundingRect.bottom <= clientHeight;
|
||||
const leftIsInViewport =
|
||||
boundingRect.left <= clientWidth && boundingRect.left >= 0;
|
||||
const topIsOutOfViewport = boundingRect.top <= offsetTop;
|
||||
const bottomIsOutOfViewport = boundingRect.bottom >= clientHeight;
|
||||
const elementSpansEntireViewport =
|
||||
topIsOutOfViewport && bottomIsOutOfViewport;
|
||||
|
||||
if (allowPartialVisibility) {
|
||||
return (
|
||||
(topIsInViewport || bottomIsInViewport || elementSpansEntireViewport) &&
|
||||
(leftIsInViewport || rightIsInViewport)
|
||||
);
|
||||
}
|
||||
return (
|
||||
boundingRect.top >= offsetTop &&
|
||||
boundingRect.left >= 0 &&
|
||||
boundingRect.bottom <= clientHeight &&
|
||||
boundingRect.right <= clientWidth
|
||||
topIsInViewport &&
|
||||
bottomIsInViewport &&
|
||||
leftIsInViewport &&
|
||||
rightIsInViewport
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue