Hey everyone. I am currently working on the following problem:There are multiple collapsibles below each other on a page. When I expand the second collapsible, the first one collapses.The problem is that when this happens, the second collapsible does not stay where it is supposed to be - it flows further up and gives the user unexpected results.
I have worked around this with a 2-step-update using Browser.Dom. But now I do have a flickering because the process is: get offset > render > get offset > adjust.
during the second get offset stage the user sees the newly rendered view with the old scroll position.
Quite ugly.
Has anyone come across this before? Any reliefs?
- in the first screenshot you can see the first collapsible - it shows all items - it has an uneven count of elements so the last row is not fill if I see all items
- second screenshot - I clicked ‘show all’ on the second collapsible - the first C gets collapsed and the second on is expanded. Because the page reflows I am now in the middle of the second (now expanded) collapsible
- position is adjusted
I want to eliminate the single frame rendered at 2
GotOffsetBeforeChange cat (Ok offset) ->
let
_ = Debug.log "before" (diff)
diff = offset.element.y - offset.viewport.y
getOffset =
Browser.Dom.getElement
(Resource.categoryToId cat)
isAlreadyOpen = model.openSection == Just cat
toggled =
if isAlreadyOpen
then Nothing
else Just cat
in
(
{ model
| openSection = toggled
}
, Task.attempt (GotOffsetAfterChange diff) getOffset
)
GotOffsetBeforeChange _ (Err _) -> (model, Cmd.none)
GotOffsetAfterChange diffBefore (Ok el) ->
let
_ = Debug.log "beforeafter" (diffBefore, diffAfter)
diffAfter = el.element.y - el.viewport.y
diffBoth = diffAfter - diffBefore
y = el.viewport.y + diffBoth
scrollToOpenSection = Task.perform (always NoOp) (Browser.Dom.setViewport 0 y)
in
( model
, scrollToOpenSection
)
GotOffsetAfterChange _ (Err _) -> (model, Cmd.none)