Streamlit-option-menu is a simple Streamlit component that allows users to select a single item from a list of options in a menu

Much appreciated @victoryhb! Nice work

Great work, @victoryhb !!! Always wanted a option menu with such style! And I’m now using it as a navi menu on the sidebar, do you have any plan to support multi level options?

1 Like

Hi @imClumsyPanda, at the moment my plan is to keep the component simple and stupid. Since adding multi-level options entails quite some work, I may only consider implementing it if there’re requests from multiple users (e.g. more than a dozen people asking).

1 Like

Okay cool! Thanks again for developing this component!

1 Like

Hi @victoryhb , I tried this component and it looks awesome as a sidebar ( instead of a bunch of radio / general buttons ). I have a few questions below:

Is there a possibility to:

  1. Make the background transparent or at least adopt the Streamlit colours? (My sidebar background is grey but the option menu background is white)
  2. Use local custom icons?
  3. Have separator lines between groups of options?
  4. Set help text for each option?

Thanks for this component. Will use this in my next project :slight_smile:

God bless

2 Likes

Hi @Shawn_Pereira! My answers to your questions:

  1. The component uses streamlit-defined colors by default, which you can customize, including setting a color to “transparent”
  2. currently not supported
  3. supported; please see the usage for the options parameter
  4. currently not supported

Hope the above helps.

1 Like

Hi @victoryhb , is it possible to set the size/font size/padding of the buttons?

Hi @imClumsyPanda, at the moment the parameters are not configurable, but if you really need them you can set them by injecting some CSS styles using st.markdown().

1 Like

Thanks a lot!

I was trying to use the Options-menu component as I would use st.expander to neatly hide options. But I didn’t quite get the behaviour I was seeing, the Code Example replicates my issue.

In the Working Example, the variables textInput_1 _2 _3 can be assigned and accessed until rerun. Whereas in the Not Working Example the assigned variables are cleared once the next “option” in the menu is chosen.
I am not sure how to get the same results as in the Working Example (it uses “with” on the st.expander object, in the Not Working Example “if” is used)

Code Example
import streamlit as st
from streamlit_option_menu import option_menu


def main():

    ################################################################
    #                        Working Example                       #
    ################################################################

    with st.sidebar:
        with st.expander('First'):
            textInput_1 = st.text_input(
                "First input", value='default 1', key='1')
            textInput_2 = st.text_input(
                "Second input", value='default 2', key='2')
        with st.expander('Second'):
            textInput_3 = st.text_input(
                "Third input", value='default 3', key='3')

        st.write(bool(textInput_1))

    if "" in [
        textInput_1,
        textInput_2,
        textInput_3,
    ]:
        st.sidebar.info("Add input in sidebar")
        return

    st.write(textInput_1, textInput_2, textInput_3)

    st.sidebar.write('---')

    ################################################################
    #                      Not Working Example                     #
    ################################################################

    with st.sidebar:
        selected = option_menu("Options Menu", ['Third', "Fourth"],
                               icons=['play', 'play'], menu_icon="cast", default_index=1)

        with st.sidebar:
            if selected == "Third":
                textInput_4 = st.text_input(
                    "First input", value='default 4', key='4')
                textInput_5 = st.text_input(
                    "Second input", value='default 5', key='5')
            elif selected == "Fourth":
                textInput_6 = st.text_input(
                    "Third input", value='default 6', key='6')

        st.write(bool(textInput_4))

        st.write(textInput_4, textInput_5, textInput_6)

        if "" in [
            textInput_4,
            textInput_5,
            textInput_6,
        ]:
            st.sidebar.info("Add input in sidebar")
            return


if __name__ == "__main__":
    st.title("Option menu component")
    main()


Hi @flight505, I think the problem is not related to the component itself, but to the way you structure your code. You may change the logic slightly to make it work, like the following:

with st.sidebar:
    selected = option_menu("Options Menu", ['Third', "Fourth"],
                           icons=['play', 'play'], menu_icon="cast", default_index=1)

    if selected == "Third":
        textInput_4 = st.text_input(
            "First input", value='default 4', key='4')
        textInput_5 = st.text_input(
            "Second input", value='default 5', key='5')
        st.write(bool(textInput_4))
        if not textInput_4 or not textInput_5:
            st.sidebar.info("Add input in sidebar")
    elif selected == "Fourth":
        textInput_6 = st.text_input("Third input", value='default 6', key='6')
        if not textInput_6:
            st.sidebar.info("Add input in sidebar")

Hi @victoryhb thanks for the help. It is working now, but every time you click the next option button the st.text_input is reset, wereas with the st.expander any change to the variable is stored until rerun. Does that mean that the option-menu component reruns the app every time you click?
And great component by the way :smiling_face_with_three_hearts:

The option-menu component will cause the app to rerun every time its value changes, just like almost all other components do. The value of any component will be kept only if it already exists on the page (even if it’s hidden with st.expander) when the change takes place. If you want to keep the value of an optionally appearing component, I think you will have to manage the session state yourself. You can check out the docs on this.

So obvious now :melting_face: - thanks

Hi, thanks for your greate work.
Do we have the parameters to set the word font size, color and background?
Thank you.

1 Like

Hi @BeyondMyself, as I replied earlier, at the moment the parameters are not configurable, but if you really need them you can set them by injecting some CSS styles using st.markdown().

OK, thank you.

@victoryhb, first of all thanks for the awesome component :slight_smile:

Can you (or @BeyondMyself ) share a quick example on how to style this streamlit_option_menu with CSS and st.markdown()?

I’ve already done this for plenty other widgets/components on Streamlit, but somehow I can’t figure it out with this one :slight_smile:

Thanks in advance!

Hi @marduk, since third-party components are embedded within an iframe, you will need to apply the CSS within the iframe. For details, see this stackoverflow post.
Be warned that doing so won’t be straightforward or pretty.
I may expose the styles directly in future if there is enough interest.

1 Like

you can open your streamlit_option_menu css file app.355290e7.css under this route:

C:\Python38\Lib\site-packages\streamlit_option_menu\fronted\dist\css\app.355290e7.css

maybe in your system, this route is different, to find the right route of file app.355290e7.css file

and rewite the content of .menu .nav-item .nav-link.active[data-v-084daf2a] {background-color: var(–primary-color) } into this:

.menu .nav-item .nav-link.active[data-v-084daf2a] {background-color: #0099ff;}

save the change of app.355290e7.css file, restart your app, you will see that the menu active background-color change into #0099ff

@victoryhb

1 Like