atdiar / particleui

A library to make frontend app development as simple as possible.
0 stars 0 forks source link

drivers/js: browser does not handle scroll restoration properly #1

Closed atdiar closed 2 years ago

atdiar commented 2 years ago

Problem Statement

Current browsers do not handle scroll restoration properly for Single Page Apps.

The desired behavior on popstate event (back or forward button was triggered) is to recover whatever scrolling position each scrollable element on the page had(ScrollTop and ScrollLeft). On pushState( i.e. when a new page is being visited), we would like to ScrollToTop (and perhaps ScrollToLeft) scrollable elements (which ones, though? wrt nested navigation).

Requirements and Implications

Proposed implementation

It should be sufficient to define a transformative function func(*ui.Element)*ui.Element that would register a scrollevent listener on "FirstTimeMounted". However this event listener shall not be registered indiscriminately: the corresponding DOM element computedStyles should include an overflowor overflow-x or overflow-y set to scrollor auto. Checking the computed styles could be done after mounting. On scroll, retrieve scrollTopand scrollLeft and store these values.

storage of the scroll offsets

These offsets are part of the User Interface state. They could be stored in session storage or in the History object.

The datastructure is likely to be aui.Object storing ui.Object equivalent to a map[id]map[offsetType]OffsetValue with id and offsetType being string types and OffsetValue being a numeric type.

A priori, History object storage will be chosen as it can already handle multiple pages. However, it requires to change the current implementation that does not have a way to store data/state for each entry.

scroll restoration

The current route / browser URL being the serialized representation of the application state, which includes the User Interface state, we should determine and apply the relevant scroll offsets on route change. The causes for route change are threefold:

  1. Back button has been hit or Forward button has been hit (popstateevent)
  2. F5 (page refresh) has been triggered
  3. A link has been hit (or navigation has been programatically triggered) (call tohistory.pushState)

In case 1, we should just restore the scrolling offsets that have been prealably stored in the history. Unmounted elements should be reset to zero (scrollTop,scrollLeft =0,0) In case 2, we would like to restore the scrolling offsets (they may be in the history but I am not sure yet) In case 3, already activated ViewElements do not remount. Otherwise, mounted Elements were previously unmounted which means reset. We just store the scrolling values.

Henceforth, on unmount(ed?), we should reset the scrolling offsets. On mount(ed?), if element is scrollable, restore scrolloffsets.

Other considerations

atdiar commented 2 years ago

It should work now.