Strange jumping between states of resizable Panel

I’m trying to create panel which will have 3 states: collapsed, half, expanded. This panel will hold some other components, like chat messages etc.

I’ve implemented it in the code below. But when I go from Expanded to Half it’s fine. When I go from Half to Collapsed, it jumps up to 90% height and back to 20%. So the end height is fine, but I don’t like this jumping transition. Is this a bug or I there is something I should understand?

YouTube Video: https://youtu.be/wKgMJg9K_eQ

MainView.ux

<App>
    <JavaScript File="MainView.js" />
    <DockPanel>
        <StatusBarBackground Dock="Top" />
        <BottomBarBackground Dock="Bottom" />
        
        <Rectangle ux:Class="MyButton" Text="no text" Padding="10" Color="#eee" Margin="3">
            <string ux:Property="Text" />
            <Text Value="{ReadProperty Text}" />
        </Rectangle>

        <Panel Height="30" Dock="Bottom">
            <Rectangle Layer="Background" Color="#00e" />
        </Panel>    

        <Panel Dock="Bottom" ux:Name="messagesPanel" Height="90%">
        <DockPanel>
            <Rectangle Layer="Background">
                <Stroke Width="1" Color="#f00" />
            </Rectangle>
            <StackPanel Orientation="Horizontal" Dock="Top">
                <MyButton Text="Up" Clicked="{goUp}" />
                <MyButton Text="Down" Clicked="{goDown}" />
            </StackPanel>
            <Panel>
                <Rectangle Layer="Background">
                    <Stroke Width="1" Color="#000" />
                </Rectangle>
                <ScrollView AllowedScrollDirections="Vertical">
                    <StackPanel Alignment="Bottom">
                        <Each Items="{messages}">
                            <Rectangle Padding="10" Margin="16,0,16,6">
                                <Stroke Width="1" Color="#333" />
                                <Text Value="{text}" />
                            </Rectangle>
                        </Each>
                    </StackPanel>
                </ScrollView>
            </Panel>

            <StateGroup ux:Name="messagesPanelState" Active="Expanded">
                <State ux:Name="Expanded">
                    <!-- <Change messagesPanel.Margin="0,144,0,0" Duration="0.3" /> -->
                    <Change messagesPanel.Height="90%" Duration="0.3" />
                </State>
                <State ux:Name="Half">
                    <!-- <Change messagesPanel.Margin="0,200,0,0" Duration="0.3" /> -->
                    <!-- <Move Target="chatCanvas" Y="y(bottomToolbar)-279" Duration="0.3" /> -->
                    <Change messagesPanel.Height="55%" Duration="0.3" />
                </State>
                <State ux:Name="Collapsed">
                    <!-- <Change messagesPanel.Margin="0,400,0,0" Duration="0.3" /> -->
                    <!-- <Move Target="chatCanvas" Y="y(bottomToolbar)-79" Duration="0.3" /> -->
                    <Change messagesPanel.Height="20%" Delay="0.3" />
                </State>
            </StateGroup>
        </DockPanel>
        </Panel>

        

    </DockPanel>
</App>

MainView.js

var Observable = require('FuseJS/Observable');
var messages = Observable();
var dummyData = [
    { text: 'message 1' },
    { text: 'message 2' },
    { text: 'message 3' },
    { text: 'message 4' },
    { text: 'message 5' },
    { text: 'message 6' }
];
messages.addAll(dummyData);

var chatState = 2;

function goUp() {
    console.log('goUp');
    if (chatState < 2) {
        setChatState(++chatState);
    }
}

function goDown() {
    console.log('goDown');
    if (chatState > 0) {
        setChatState(--chatState);
    }
}

function setChatState(stateIndex) {
    switch (stateIndex) {
        case 2:
           messagesPanelState.goto(Expanded);
           console.log('Expanded');
           break;
       case 1:
           messagesPanelState.goto(Half);
           console.log('Half');
           break;
       case 0:
           messagesPanelState.goto(Collapsed);
           console.log('Collapsed');
           break;
       default:
           console.log('Undefined state');
    }
}

module.exports = {
    messages: messages,
    goUp: goUp,
    goDown: goDown
};

There is no bug, that is how the animations work when you use them in the way you did.

A better approach that also results in the exact behaviour you’re after would be to use LayoutAnimation which describes how the element transitions between the different states. Here’s the code, based on what you posted:

<App>
    <JavaScript>
        var Observable = require('FuseJS/Observable');
        var messages = Observable();
        var dummyData = [
            { text: 'message 1' },
            { text: 'message 2' },
            { text: 'message 3' },
            { text: 'message 4' },
            { text: 'message 5' },
            { text: 'message 6' }
        ];
        messages.addAll(dummyData);

        var chatState = 2;

        function goUp() {
            console.log('goUp');
            if (chatState < 2) {
                setChatState(++chatState);
            }
        }

        function goDown() {
            console.log('goDown');
            if (chatState > 0) {
                setChatState(--chatState);
            }
        }

        function setChatState(stateIndex) {
            switch (stateIndex) {
                case 2:
                   messagesPanelState.goto(Expanded);
                   console.log('Expanded');
                   break;
               case 1:
                   messagesPanelState.goto(Half);
                   console.log('Half');
                   break;
               case 0:
                   messagesPanelState.goto(Collapsed);
                   console.log('Collapsed');
                   break;
               default:
                   console.log('Undefined state');
            }
        }

        module.exports = {
            messages: messages,
            goUp: goUp,
            goDown: goDown
        };
    </JavaScript>
    <DockPanel>
        <StatusBarBackground Dock="Top" />
        <BottomBarBackground Dock="Bottom" />
        
        <Rectangle ux:Class="MyButton" Text="no text" Padding="10" Color="#eee" Margin="3">
            <string ux:Property="Text" />
            <Text Value="{ReadProperty Text}" />
        </Rectangle>

        <Panel Height="30" Dock="Bottom" Color="#00e" />

        <Panel Dock="Bottom" ux:Name="messagesPanel" Height="90%">
            <LayoutAnimation>
                <Move Vector="1" RelativeTo="PositionChange" Duration="0.3" />
                <Resize Vector="1" RelativeTo="SizeChange" Duration="0.3" />
            </LayoutAnimation>
            <DockPanel>
                <Rectangle Layer="Background">
                    <Stroke Width="1" Color="#f00" />
                </Rectangle>
                <StackPanel Orientation="Horizontal" Dock="Top">
                    <MyButton Text="Up" Clicked="{goUp}" />
                    <MyButton Text="Down" Clicked="{goDown}" />
                </StackPanel>
                <Panel>
                    <Rectangle Layer="Background">
                        <Stroke Width="1" Color="#000" />
                    </Rectangle>
                    <ScrollView AllowedScrollDirections="Vertical">
                        <StackPanel Alignment="Bottom">
                            <Each Items="{messages}">
                                <Rectangle Padding="10" Margin="16,0,16,6">
                                    <Stroke Width="1" Color="#333" />
                                    <Text Value="{text}" />
                                </Rectangle>
                            </Each>
                        </StackPanel>
                    </ScrollView>
                </Panel>

                <StateGroup ux:Name="messagesPanelState" Active="Expanded">
                    <State ux:Name="Expanded">
                        <Change messagesPanel.Height="90%" />
                    </State>
                    <State ux:Name="Half">
                        <Change messagesPanel.Height="55%" />
                    </State>
                    <State ux:Name="Collapsed">
                        <Change messagesPanel.Height="20%" />
                    </State>
                </StateGroup>
            </DockPanel>
        </Panel>

    </DockPanel>
</App>