Build responsive apps based on different screen features

Perhaps you have been in this situation. Busy building your streamlit app on you 17inch wide laptop. Everything looks fly:

Then you realise users might access your app from their tablet or phone. So you open up your developer tools not expecting much of a change only to see:

Perhaps if I had a way to tell what the screen size is and when it changes to show different types of an app. You could use st_javascript to get the screen width size at the start of your app using some javascript or streamlit_js_eval which seems much simpler. In addition to these options, I created a library that pulls some important screen data based on dynamic changes to the screen that looks like:
image

You can use these to conditionally render different formats/version of your app.

The demo app is here, the github repo and the pypi.

Happy streamliting.

11 Likes

nicely done @Rushmore it will surely be useful in my next upcoming project

1 Like

Hi @Rushmore,

I tried your library today (after pip installing the recommended 3 packages). Just wanted to let you know a few points:

The code I used was:

import streamlit as st
from st_screen_stats import ScreenData     # pip install streamlit-screen-stats

screenD = ScreenData(setTimeout=1000)
screen_stats = screenD.st_screen_data_window_top()
st.info(f"Scn Width: {screen_stats['screen']['width']}")

Running the above script, it gave the following error on the 1st pass:

And immediately thereafter, the error disappeared and gave me the desired result (on the 2nd pass)

It happens very quickly and can easily be bypassed with a try-except enclosure. Thought, I’d mention this to you, in case you want to try and investigate the source of the error (which only happens on the 1st pass).

Other than that, this is super useful as a streamlit app (with multiple st.columns) display weirdly on a mobile.

Another suggestion: besides the screen stats, there are other end user parameters which will be very helpful to collect: IP address / location / local time / etc., for the purpose of user / country / local time / etc. identification, so that suitable code can be written for those user categories. Maybe, your library can cover an entire end user profile, instead of just end user screen stats.

Thank you for this library. Will start using it henceforth. :slight_smile:

Cheers

Hey Shawn, glad you liked the component.

Regarding your points:

  1. Yeah, so this part of the component waits 1 second before delivering the data. The setTimeout param at 1000 is telling the component to wait 1 second before delivering data to the component. The best thing to do is to set a time.sleep for 2 seconds or like you said do a try and except block. I use a while loop, to wait for data from the component before running the rest of the app albeit I use the other class from the component WindowQuerySize which delivers data only when the window size changes. It works kinda like CSS’ @media screen queries.
  2. Thanks for the recommendations, will work on these other attributes and update the package.

Thanks for the feedback, its always appreciated :smiley:

Hey @Shawn_Pereira

Finally got round to doing some debugging.

  1. Placed a timeout at the python level to stop the error at the 1st pass/run of the component. It adds 1 second to the setTimeout parameter a user adds.
  2. Created browser-detection-engine here to get more details from user browser. Will add more data as I too need it for my app.
1 Like

More updates***

  • Have added a callback for on_change.
    Reason:
    • The component works such that on first mount/app load it sends the value to streamlit.
    • Subsequent app reloads will most likely return None or the value selected for the default parameter unless there has been a change in the size of the screen.
    • To make sure you only get a value when there has been a legitimate change in the screen width/size, utilise the on_change parameter to set the results on change of the screen width to a session_state value.
from st_screen_stats import ScreenData, WindowQuerySize, WindowQueryHelper

helper_screen_stats = WindowQueryHelper()

def onScreenSizeChange(updated_screen, component_function_):

    st.session_state[updated_screen] = st.session_state[component_function_]

if "large_screen_size_" not in st.session_state:
    st.session_state["large_screen_size_"] = helper_screen_stats.window_range_width(min_width=1000, max_width=1100, key="lg_screen")
else:
    helper_screen_stats.window_range_width(min_width=1000, max_width=1100, on_change=onScreenSizeChange, args=("large_screen_size_", "lg_screen_post_first_mount",) key="lg_screen_post_first_mount")

if st.session_state["large_screen_size_"]["status"]:
    st.write("rest of code here")

# Also works for `ScreenData` and `WindowQuerySize` classes

1 Like

Okay, fixed a few things to make component more reliable.

  • I noticed whilst using the component that I would regularly get None/null arguments because I was using the window.top to get the width/screen dimensions. I have since changed this to window.parent which has proved to be more reliable.

Latest update 0.0.69.

2 Likes

Latest update: 0.0.75

  • no need for pause or time.sleep. Automatically waits for result from browser before rendering result into your app.
1 Like