Measurement Anchor Mode for <transition-group>
What problem does this feature solve?
Currently, <transition-group>
s measure the position of the element from the top left of its bounding box. This works well for purely left-to-right and top-to-bottom situations. However, in some cases, children may change in ways that suggest they are anchored at the bottom or right of their bounding box. This can cause the element to appear to unintuitively jerk up before transitioning again to the correct position.
One example (my use case) is a chat-style application where an item within the chat message list has a part that is hidden after a certain amount of time. In my case, scrolling in the list starts from the bottom. I want the older messages in the list to transition downward to close the now vacant space without causing the changed element to jerk up first. Currently I see no easy workaround to enable me to use transition-group without this jerking. I may have to re-implement the FLIP animation myself, which feels bad.
Another use case is right-to-left text modes.
Currently, in the source code, left
and top
properties of ClientRect are hard coded. Adding an option to instead measure the delta from the right
and bottom
of the rect would be a simple change that would enable me use transition-group for my use case.
Codesandbox showing actual and desired behavior: https://codesandbox.io/s/transition-group-bottom-anchored-example-nv3bh?file=/src/App.vue
What does the proposed API look like?
Add an anchor
prop, where the options are:
anchor = "top" | "top-right" | "right" | "bottom-right" | "bottom" | "bottom-left" | "left" | "top-left"
where each implies measuring from that corner or midpoint.
Or, more simply:
anchor = "start" | "end"
where "start" means "measure from the top left" and "end" means "measure from the bottom right"
Example:
<transition-group tag="ul" name="transition-name" anchor="end" class="list">
<li class="list-item" v-for="item in items" :key="item.key">{{ item.text }}</li>
</transition-group>
In this example, .list-item
s appear to have a "downward gravity," so when a .list-item
changes in height, the items above it will move down, but the .list-item
's bottom edge will not have moved.
For the moment, I'm working around the problem by "cloning-and-owning" the source code for TransitionGroup. Simply changing top to bottom; and left to right does exactly what I needed it to do.
do you have a boiled down repro to illustrate the bug? Are you changing the origin of the translation after the element is added?
This has to do with the reference point on the measured ClientRect used to calculate the translation delta between the start and end states of the F.L.I.P. animation. Measuring from the top-left is not appropriate for lists whose "gravity" tends to the right or downward, such as in chat applications or horizontal lists in rtl languages.
The problem is subtle, but when you notice it, it's quite annoying.
I created this codesandbox to show the actual and desired behavior: https://codesandbox.io/s/transition-group-bottom-anchored-example-nv3bh?file=/src/App.vue
Oh, so you are changing the size of an element inside of the transition-group
and you want it to stay where it was independently of what changed inside?
Thanks for the clear reproduction with the actual desired behavior 🙌
I'm not sure if this should and could work out of the box, otherwise, the idea of adding a new prop seems alright, it should probably go through an RFC for naming and edge cases
I think this one is worth having open because it really shows a case that can be improved and how to implement it, but that's my just opinion.
@eli-crow do you feel like opening an RFC at https://github.com/vuejs/rfcs? You seem to have a lot of content already, the idea would be to be more problem-centric to make sure the proposed api can solve all the edge cases as well
@posva Exactly. But defining "stay where it was" is dependent on which direction gravity is pointing.
I'll see if I have some time to submit an RFC this week.
Submitted my first RFC here: https://github.com/vuejs/rfcs/pull/262 Feel free to close this issue.