Inwerpsel / use-theme-editor

A React theme editor
GNU General Public License v3.0
4 stars 0 forks source link

Restore scroll offset of UI elements when navigating history #57

Closed Inwerpsel closed 10 months ago

Inwerpsel commented 10 months ago

Problem

Currently, many UI elements can be very long and cause a lot of scrolling. Mainly in the inspector and drawer, but could be others.

When navigating history, the scroll position is often not preserved. Specifically in case the element was removed in a later state in history, then recreated when moving back.

Solution

If the scroll offset of such elements (or the right parent container) is saved in the history timeline, it can be restored as the element is recreated.

A similar problem occurs when dragging an element into another area, perhaps the same solution can be used.

Challenges

How to determine which elements should be tracked?

Currently, it's mostly the areas that are scrollable. All contained elements add to its height (maybe a few exceptions).

The main advantage of this is that it keeps the total UI simpler, as nested scrolling sections are almost always tedious to use, they lead to a lot of mistakes and corrections.

So probably it's best to keep this simple approach and implement scroll tracking only for the areas. This does mean that inner components need to ensure the same height when restored from history.

Using scrollIntoView vs restoring exact scroll position

It seems best to not only use scrollIntoView, as it will rarely match up with the previous position of things. It also requires keeping track of more elements. The main benefit is it would be resilient against changes in the area height.

Storing the exact scroll position should work, at least for now. All elements should already rerender at the same height with very few exceptions.

Perhaps a combination of both is possible, maybe even using a user toggle.

Which events should trigger recording scroll offset?

If the scroll offset of areas is used, it's probably fine to just recording the scroll position whenever it changes, with debouncing/throttling.

Another appealing option is to record any changes to the scroll position that happened between any 2 actions in history. This should be manageable, as those actions are all debounced already. It could even be stored as a property on these actions directly.

An interesting question is whether scroll events should modify an older history entry when navigating an older state. Doing this would provide a similar experience to how browsers handle the scroll position when navigating history. This could also be turned into a user toggle as both behaviors could be useful.

Puts restrictions on UI elements that affect height but are not tracked in history

There's a few such elements, like the toggle to look for scoped selectors of an element, and some innards of variable controls.

It's probably OK to ignore this for now, as it only causes scroll offset mismatches if this UI is changed before navigating to another state in history. Perhaps some small changes can be done in variable control to restore more of the UI.

If this happens more frequently, it can be solved by either storing the state in history (if it's useful), or by providing some fixed height.