Version 1.52.0

Highlights

Notable Changes

  • :musical_keyboard: You can configure keyboard shortcuts for buttons (#12975, #1291).

  • :red_question_mark: You can now pass query parameters to st.switch_page and st.page_link (#13027, #8102, #8112, #13093).

  • :wavy_dash: st.html has a new unsafe_allow_javascript parameter to execute JavaScript (#12918).

  • :up_arrow: st.metric has a new delta_arrow parameter to configure the visibility and orientation of the delta arrow (#12982, #4775).

  • :keyboard: You can configure the horizontal alignment of st.markdown, st.caption, st.title, st.header, st.subheader, and st.text with a new text_alignment parameter (#13032, #4109, #13034, #13036).

  • :cyclone: You can use a spinner everywhere you can set an icon and in the avatar parameter of st.chat_message. The spinner can’t be used as a page favicon (#13045, #6415).

  • :hammer_and_wrench: You can now add tooltips to st.badge (#12897, #12878). Thanks, marcolanfranchi!

  • :hole: You can configure placeholder text for null values in st.dataframe and st.data_editor with a new placeholder parameter (#12968, #7360).

  • :key: To prevent widgets from resetting when you change a parameter, widgets are transitioning to an identity based only on their keys (if provided). The following widgets use only their key for their identity:

    • st.file_uploader

    • st.camera_input

  • :up_down_arrow: st.plotly_chart has a height parameter to use with flex containers (#12593).

  • ↔️ st.container, st.dataframe, and st.data_editor support width="content" (#12848, #12875, #12391).

  • :snake: Streamlit supports Python 3.14 and Vega-Altair 6!

  • :ghost: st.bokeh_chart has been removed. Use the streamlit-bokeh custom component instead.

  • :skull_and_crossbones: **kwargs is deprecated in st.vega_lite_chart (#13141).

  • :poop: The .add_rows() method is under consideration for removal. Please leave feedback (#13063).

  • :busts_in_silhouette: We’re improving community contributions by using a public workflow for discussing feature specs (#12248).

Other Changes

  • :toothbrush: For better performance, Streamlit uses uvloop if it’s installed (#13047).

  • :soap: For improved performance, Markdown plugins are lazy loaded (#13152).

  • :sponge: To improve load times, we reduced the bundle size (#13071, #13077, #13099, #13115, #13128).

  • :bathtub: To improve performance, we’ve refactored session context data (#12788, #12789, #12790, #12791).

  • :shower: The hovering performance of st.line_chart was improved (#13156, #13154).

  • :broom: st.metric was optimized to prevent poor hovering performance with large data sets (#12983).

  • :alien: The packaging Python dependency is no longer version-capped (#13073).

  • :dotted_line_face: For clarity, Streamlit logs a warning if you try to hide a non-range index when using st.data_editor with num_rows="dynamic". A non-range index must be editable to add rows (#12978, #8263).

  • :butterfly: Bug fix: Streamlit auth raises a warning instead of an error when browser back navigation revisits a consumed OAuth callback (#13127, #13101).

  • :crab: Bug fix: The WebSocket timeout was increased on Android to improve st.file_uploader performance (#13132, #11419).

  • :lizard: Bug fix: Query parameters are preserved when using browser back and forward navigation (#13129, #9279).

  • :snail: Bug fix: For custom components v2, the frontend key is correctly computed to be stable if it has a key in Python and otherwise change when its parameters change (#12950).

  • :spider_web: Bug fix: Empty code blocks in Markdown don’t display “undefined” (#13074, #12986). Thanks, ashm-dev!

  • :cricket: Bug fix: st.feedback is prevented from wrapping (#12970, #12068).

  • :scorpion: Bug fix: Custom components v2 don’t raise a warning when placeholders are replaced as a result of the initial manifest scan (#13043, #13042).

  • :mosquito: Bug fix: st.audio_input has the correct padding for its waveform (#13010).

  • :microbe: Bug fix: The date and time icons in st.data_editor are visible in dark mode (#12994, #12852). Thanks, aritradhabal!

  • :fly: Bug fix: st.pills and st.segmented_control wrap correctly when width="content" (#12969, #12067, #12879, #12857).

  • :cockroach: Bug fix: st.color_picker has a minimum width to prevent a pixel width below its intrinsic size (#12962, #12872).

  • :spider: Bug fix: Disabled widgets hide their borders (#12949).

  • :lady_beetle: st.audio_input and st.chat_input show a clearer message when microphone permissions are insufficient (#12914).

  • :honeybee: Bug fix: st.navigation uses the sidebar font and Streamlit falls back to its built-in fonts if a font can’t be found (#12948).

  • :ant: Bug fix: MultiselectColumn doesn’t raise a ValueError when adding new rows in st.data_editor (#12860, #12936, #12815). Thanks, kkchemboli!

  • :beetle: Bug fix: MultiselectColumn works correctly when the underlying dataframe has an empty column (#12935, #12842).

  • :bug: Bug fix: st.text_area avoids negative height calculations that produce invalid CSS (#12891, #12867).

4 Likes

Amazing work one time more, guys! Many interesting updates in this release (query params, audio in chat input…).

Now I am waiting for the dynamic/deferred tabs in the next release (hopefully)

did anything in the new release change the behavior of st.number_input? For example, I have:

st.number_input(‘Input:’, min_value=-5.00, max_value=5.00, value=-0.5, step=0.01)

This used to behave fine, but now if I try to type a number with more than 1 keystroke, e.g. “-0.65” it is impossible. It won’t register the “-” at all, and if I try to type “0.65” it will basically ignore everything after “0” and then treat the “6” keystroke as a sort of “add 1” so I end up with “0.01”. It’s become completely unusable as an input method for me.

Not sure if it’s just a me problem or not! If you have any ideas please let me know! Thanks all!

Are you using your numeric keypad, and is the Num Lock off by any chance?

Indeed it seems to be a you problem. It works for me.

When passing a callable to st.download_button, what is the best way to gracefully handle cases where data generation fails?

There isn’t a way to catch the error in your main app script, currently. I filed a feature request for it, so you can comment or upvote it for the devs to track:

1 Like