reactour icon indicating copy to clipboard operation
reactour copied to clipboard

Scrolling to the element specified in highlightedSelectors that is located outside the viewport does not work

Open altq33 opened this issue 9 months ago • 1 comments

Hi, I ran into a problem. When I specify a bunch of mutationObservables and highlightedSelectors, and as an element before loading the data, I specify the element in the selector prop. { selector: "[data-record-tour='loader']", highlightedSelectors: ["[data-record-tour='anamnesis-next-step']"], mutationObservables: ["[data-record-tour='loader']"], }

After the download takes place and the loader disappears, [data-record-tour='anamnesis-next-step'] is correctly selected, but it is outside the viewport and scrolling does not occur. This case works precisely in a situation with asynchronous loading of a step. I was able to repeat this using an example from the documentation. Are there any options for what to do about it? Example Link https://codesandbox.io/p/sandbox/tour-with-data-fetching-forked-yzwfx3

altq33 avatar Mar 10 '25 08:03 altq33

I solved the problem in the following crutch-like way. I added the triggerReselect function, which is able to reselect an element in a similar way to the library. It uses a scroll to the element and a dispatchEvent resize which triggers a reselect in the library. Next, I just called this function for a specific step after executing asynchronous logic.

const triggerReselect = useCallback(
  (keyCondition) => {
  	const { key, selector, highlightedSelectors } = steps[currentStep] || {};
  	if (!isOpen || (keyCondition && key !== keyCondition)) return;
  	const targetElement = document.querySelector(
  		highlightedSelectors?.[0] || selector
  	);
  	if (!targetElement) return;
  	targetElement.scrollIntoView({ block: "nearest" });
  	window.dispatchEvent(new Event("resize"));
  },
  [currentStep, isOpen, steps]
);

I also added this effect to the step component in order to exclude cases when the element is partially outside the viewport and the library does not scroll to it completely when the step is changed.

useLayoutEffect(() => {
  const element = document.querySelector(
  	highlightedSelectors?.[0] || selector
  );
  element?.scrollIntoView({ block: "nearest" });
});

altq33 avatar Apr 02 '25 12:04 altq33