dotnet / aspnetcore

ASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux.
https://asp.net
MIT License
35.44k stars 10.02k forks source link

Introduce the concept of state transitions in Blazor to allow for e.g. animations #10389

Open tomRedox opened 5 years ago

tomRedox commented 5 years ago

Is your feature request related to a problem? Please describe.

Following on from my StackOverflow question...

In my Blazor components I often render components based on either a conditional statement, e.g.

@if (_contact.IsCustomer)
{
    <SalesOrdersList Customer="@_contact" />
}

Or from a loop, e.g.

@foreach(var salesOrder in _customer.SalesOrders)
{
    <SalesOrderSummary SalesOrder="@salesOrder" />
}

When I change the state I'd like to animate the state transition so that the components fade in/out. In the examples above that might happen when IsCustomer changes, or when a record is added or removed from the SalesOrders collection.

Animating adding a component can be done with CSS, but I think that animating the removal of a component will be impossible because it simply doesn't exist in the next render, so there's nothing to hang the animation onto?

Describe the solution you'd like

In React there used to be a series of attributes related to state transitions, which now seem to have been replaced by react-transition-group. That looks like a big hammer for what seems like a fairly small nut.

Ideally I'd favour something really simple to use, like having an on-removal-class attribute for the name of a CSS class that's then added to the component, and allowed to complete, when the item is identified for removal from the render tree. That seems like it may be possible, because if I understand Blazor correctly the new and old render trees are diff'd to work out what parts to re-render?

There are potentially lots of other things you might want to happen in a state transition too, and no-doubt some that can't be handled with CSS alone, but I think the animation side of things is fairly important to aid users in understanding the consequences of a particular UI interaction?

mkArtakMSFT commented 5 years ago

We've moved this issue to the Backlog milestone. This means that it is not going to happen for the coming release. We will reassess the backlog following the current release and consider this item at that time. However, keep in mind that there are many other high priority features with which it will be competing for resources.

rxelizondo commented 5 years ago

Perhaps this is implied in the original post, but another thing that would be really nice to have animated would be page transitions.

Essentially, it would be nice that as you navigate from page to page, the new pages would swoop in and out from the left, right, up or down depending on some setting. I am very new to Blazor so I am not sure if this is possible to do right now but I have a feeling it is not.

dazinator commented 5 years ago

This is something that other client side frameworks such as @SteveSandersonMS's knockoutjs made very easy. I know that Blazor is still fairly premature but features like this make demo's cooler, so naturally I thought it would have been in since the first alpha! :-) I guess showing dll's written in c# and loaded into a browser was enough to sell audiences at demo's (it was enough to sell me, but see note below) but come on.. transitions on DOM content added or removed from the tree is surely a must have feature? Oh -if anyone is able to share a link to a blazor sample app that does simple transitions of DOM content it would be useful.

Note: because now I have to sell my bosses on the blazor apps that I am writing - and they don't gasp as much when I show them the bit where the dll's are running in the browser. In fact they don't gasp at all :-( - they just look at the empty white page and wonder why when the first page finally appears it doesn't swoop in fancily from the right hand side like their old application did!

dazinator commented 5 years ago

I settled on the following solution to applying a transition to an element before removal, it's not the greatest because I am using Task.Delay with a specified time in milliseconds which needs to match up o the duration of the transition specified in the css:

Reusable Transition.razor component;

<div class="@(ToggleActive ? ToggleTransitionOnCssClassName: ToggleTransitionOffCssClassName)">
    @ChildContent;
</div>

@code {

[Parameter] RenderFragment ChildContent { get; set; }

[Parameter] string ToggleTransitionOnCssClassName { get; set; } = "";
[Parameter] string ToggleTransitionOffCssClassName { get; set; } = "";

[Parameter] int TransitionDurationMilliseconds { get; set; } = 200;

public bool ToggleActive { get; set; }

[Parameter] EventCallback<bool> TransitionEnded { get; set; }

public async Task ToggleTransition()
{
    ToggleActive = !ToggleActive;
    await Task.Delay(TransitionDurationMilliseconds);
    await TransitionEnded.InvokeAsync(ToggleActive);
}

}

and it's used like so from a parent page or component:


       @if (RenderThingy)
        {
            <Transition @ref="Transition" TransitionDurationMilliseconds="500" ToggleTransitionOnCssClassName="m-fadeOut" ToggleTransitionOffCssClassName="m-fadeIn" TransitionEnded="@TransitionComplete">
                <RenderThingy OnDismissed="@OnDismissed"></RenderThingy>
            </Transition>
        }

@code {

    Transition Transition { get; set; }

    bool RenderThingy {get; set;} = true;

    async Task OnDismissed()
    {
        await Transition.ToggleTransition();
    }
    private void TransitionComplete(bool toggleState)
    {
        RenderThingy = false;
    }
}

and css:

.m-fadeIn {
    visibility: visible;
    opacity: 1;
    animation: fadein 500ms;
}

@keyframes fadein {
    from {
        opacity: 0;
    }

    to {
        opacity: 1;
    }
}

.m-fadeOut {
    animation: fadeout 500ms;
}

@keyframes fadeout {
    from {
        opacity: 1;
    }

    to {
        opacity: 0;       
    }
}
HMackenzie commented 5 years ago

@tomRedox Did you manage to get anywhere with this? I'm currently building a chart where I want items to animate between state changes. I'm currently getting around it by toggling a boolean as a parameter on each component I want to animate (quite similarly to @dazinator 's suggestion above). However, this is pretty awful, as it results in basically everything re-rendering.

dazinator commented 5 years ago

I hate my "solution".. blazor needs something proper for this!

tomRedox commented 5 years ago

@Weezeal no I'm afraid not, from experience with React I don't think there really is anywhere to go until the framework incorporates something we can use for this.

The stack overflow question is at 600 views and 1 upvote in 4 months, so I guess there's not that much demand for this yet, but I agree with @dazinator that this is one of those things that clients and managers have got so used to seeing in apps built with other SPA frameworks that it's now slightly jarring when an app doesn't do it; it's the sort of thing that non-technical people spot.

SteveSandersonMS commented 5 years ago

The solution I'd expect is to create an animator component that renders either a list or a single item, and incorporates logic to delay the removal of each item so it can be animated out. Blazor already has good primitives for templates components, so the resulting APIs should be pretty nice. This would be essentially the same solution that is used in other SPA frameworks.

This is achievable in user code and doesn't require a built-in framework feature. I'm not saying it's easy, but hopefully someone in the community will find time to do it. It's something I may do myself at some point but have other priorities in the short term.

dazinator commented 5 years ago

@SteveSandersonMS

, and incorporates logic to delay the removal of each item so it can be animated out.

Not sure if this was the best approach but I tried this but I don't like it because suppose you are animating a fade out transition, in your css you might specify a value such as 2 seconds to fade over. In blazor you must now task.delay the removal by atleast 2 seconds otherwise the UI element will be removed before the animation completes. So the animation timing value (2 seconds) is specified in the css, yet you now must also specify 2 seconds when using the blazor animator so it can defer removal by the right amount to tie up with the animation.et they are now If you decide to change the css to fade out over 3 seconds you now must change the corresponding blazor delay value to 3. It works, and is the approach I an using for lack of any other, but there has to be a better solution, onee that makes better use of events in the DOM to work out when an animation has completed so removal can be deferred until that event is received,. That way you wouldn't need to specify any delay value like 2 or 3 seconds etc on the blazor side and animation timings can be left purely managed in css

SteveSandersonMS commented 5 years ago

Yes, you can implement any strategy you want for deciding how long the delay should be. It could delay until some DOM event occurs.

dazinator commented 5 years ago

Ok thanks. I'll try and revisit this at some point then and see if I can get past that final hurdle. If it works out I'll open source something and post a link here.

dazinator commented 5 years ago

Here is my solution: https://github.com/dazinator/BlazorDeferredRemove Provided a couple of helper components that can wait for a CSS property transition, or css animation to complete, before removing some content.

VaclavElias commented 4 years ago

Another solution https://github.com/mikoskinen/Blazor.Animate

NVentimiglia commented 4 years ago

This is my number one blocker for adopting blazor. I need to know that I can keep my application beautiful with intro, outro, update, and list-move transition animations. I really enjoy the solution that Vue.JS came up with. It solves all my perceived use cases in a very non-obtrusive way. The solution is much like Blazor.Animate in that we wrap the html in a component.

https://github.com/NVentimiglia/Blazor.Transitions

https://vuejs.org/v2/guide/transitions.html

https://github.com/mikoskinen/Blazor.Animate/issues/10

ghost commented 2 years ago

We've moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process.

Dedigraz commented 2 years ago

I don't know whether this issue is still actively being researched, but I believe there's some great progress in the shared element transition proposal that the blazor team could look at.

0xakihiko commented 2 years ago

I'd like to throw in a request for this as well, it seems like a staple in most libraries.

ghost commented 2 years ago

Thanks for contacting us.

We're moving this issue to the .NET 8 Planning milestone for future evaluation / consideration. We would like to keep this around to collect more feedback, which can help us with prioritizing this work. We will re-evaluate this issue, during our next planning meeting(s). If we later determine, that the issue has no community involvement, or it's very rare and low-impact issue, we will close it - so that the team can focus on more important and high impact issues. To learn more about what to expect next and how this issue will be handled you can read more about our triage process here.

MarkusRodler commented 2 years ago

Maybe the upcoming Shared Element Transition API could help: https://developer.chrome.com/blog/shared-element-transitions-for-spas/

ghost commented 1 year ago

We've moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process.

oliverw commented 1 year ago

"We've moved this issue to the Backlog milestone." - This is turning into "Groundhog Day" 😄

mkArtakMSFT commented 12 months ago

The View Transitions API seems promising. Unfortunately, it's not yet supported by all major browsers: https://developer.mozilla.org/en-US/docs/Web/API/View_Transitions_API#browser_compatibility

MarkusRodler commented 12 months ago

The View Transitions API seems promising. Unfortunately, it's not yet supported by all major browsers: https://developer.mozilla.org/en-US/docs/Web/API/View_Transitions_API#browser_compatibility

@mkArtakMSFT Yeah I know, Internet Explorer 11 support is not that good 😉 Joking aside, would it still be an option to implement the feature with it, even if the rest of the browsers still have to follow suit? In principle, it would be better than nothing.

In my opinion users could benefit from the feature while users with unsupported browser will not notice that it does exist.

SteveSandersonMS commented 12 months ago

For people who are interested in using View Transitions, have a look at this: https://github.com/jsakamoto/Toolbelt.Blazor.ViewTransition