TangleSpace / hydralit_components

A package of custom components for Streamlit and Hydralit. Can be used directly or in combination with the Hydralit package.
Apache License 2.0
185 stars 21 forks source link

Loader animation moves all the dashboard #9

Closed RaulGG033 closed 2 years ago

RaulGG033 commented 2 years ago

Hello,

First of all thank you very much for the incredible library, I really love it and was waiting long time for something like this!

I wanted to ask if there's any possibility to deactivate the loading animations or use the original streamlit one to avoid this animation to move the dashboard (the loading appears on top and moves the user's view, making it a bit uncomfortable in some apps). Another option would be to make the loading animation float in front of the dashboard without modifing the structure.

Thank you in advance!

TangleSpace commented 2 years ago

I'm sorry, I'm not sure exactly what you mean, if you could possible provide some screenshots for example? I haven't seen the loaders shift any content, as they are may to be an overlay, so technically they are rendered over the top of everything so they don't shift any of the content. Thanks

RaulGG033 commented 2 years ago

Hello @TangleSpace, thank you very much for your answer.

In my case it renders at the start of the dashboard, and this moves all the plots of the dashboards down during the loading time. Then the loader closes and the plots go again to the original position.

When loading a new "tab", this is not a problem, but when loading after using one filter at the middle of the dashboard it is a bit frustrating visually (feels like the app starts jumping).

Here an screenshot. Top orange/red is the nav panel. Down the automatic loader moving all the dashboard down (the last orange/red part indicating market analysis). I would like to be able to disable this loading animation at some points.

image

PD: I didn't modify any animation related part, this is how I load the app:

    over_theme = {'txc_inactive': '#FFFFFF'}
    app = HydraApp(
            title='My app',
            favicon="🚗",
            hide_streamlit_markers=False,
            #add a nice banner, this banner has been defined as 5 sections with spacing defined by the banner_spacing array below.
            use_banner_images=[picture_path, None,  {'header':"<h1 style='text-align:center;padding: 0px 0px;color:grey;font-size:250%;'>App name</h1>"}, None, picture_path], 
            banner_spacing=  [15,10,70,10,15],
            use_navbar=True, 
            navbar_sticky=False,
            navbar_animation=True,
            navbar_theme=over_theme,
        )

    # Home and about 📧
    app.add_app("Home", icon="🏠", app= Home_Tab(),is_home=True)

I use the app.add_app method

TangleSpace commented 2 years ago

Thanks for the great amount of detail, very helpful. I can understand, it's a matter of personal choice. There is an easy solution to customise the way the loader works by creating your own loader! it can simply do nothing and then you won't see anything, or you can change it to use a Streamlit default, you can even check which app is being loaded and use a different one per app.

In the hydralit example repo, i use a custom loader to demonstrate how to detect the app and customise the experience. In hydralit there is a default loader, that is the one you're seeing usually, you can replace it with your own as below to have any type of behaviour you want.

Since your using the add_app method, this is great, as you can just use the app.add_loader_app method, as show in the example.

The code for the custom loader in the example is located here, it has the same structure as the normal apps you add, with the exception that the run method accepts another argument, which is a reference to the app that is going to be loaded. As you can see, that app_target variable is a reference to the app that is being requested to run from the parent, you do anything you want, display anything, then call the run() method on that target app. In this case, you wrap the call app_target.run() with a custom loader or one of the info messages or something from Streamlit. Animation gone, so you get the look you're after. If you want the loader for some apps and not others, just check the name of the app as per the example and you can customise it.

`def run(self,app_target):

    try:
        app_title = ''
        if hasattr(app_target,'title'):
            app_title = app_target.title

        if app_title == 'Sequency Denoising':
            with HyLoader(se_loader_txt, loader_name=Loaders.pacman):
                time.sleep(int(self.delay))
                app_target.run()

        elif app_title == 'Loader Playground':
            app_target.run()
        else:
            with HyLoader("✨Now loading {}".format(app_title), loader_name=self._loader,index=[3,0,5]):
                time.sleep(int(self.delay))
                app_target.run()

    except Exception as e:
        st.image("./resources/failure.png",width=100,)
        st.error('An error has occurred, someone will be punished for your inconvenience, we humbly request you try again.')
        st.error('Error details: {}'.format(e))`

Hope that helps and thanks.

RaulGG033 commented 2 years ago

@TangleSpace Thank you again for your support.

I have been trying to use the default Streamlit loader using as a guide this example but I haven't been able to do this until the moment.

Edit: I just tried the following and it worked (i.e. using this lines no loading animation is displayer):

with HyLoader(loader_name=self._loader,index=[]): app_target.run()

TangleSpace commented 2 years ago

glad you got it working the way you want.