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

Really? Awesome! Thanks!!!

Very awesome, thanks @victoryhb ! You’re the man. Looking forward.

Hi, I love this component, thank you for sharing with us !

I was wondering if there was any way to change the displayed page by clicking on a button or something ?

For example, on page 1 I could ask users to fill out different parameters and when they click a submit button it would send them on page 2 and run a function with their chosen parameters ? I know I can make it all happen on the same page but I’d like to keep things separated while still have some interconnection between pages…

Though, I’d understand if that is outside the scope of this project.

Hi @florianbrnrd, AFAIK, there is no concept of “page” in Streamlit. However, different states resulting from user actions can be saved in the session state, which you can use to select a particular menu item (using default_index) when the same code is run again after button clicks.

Hi, thanks for the reply.
I understand what you mean but since your option-menu makes it possible to show different pages/app/content based on what is selected it made me think it would be nice to be able to “propagate” some data from one page/app to the other.
I did some testing on my own and I eventually came up with what you described, and it worked fairly ok using session_state, but -indeed- the way streamlit works (and rerun pages from top to bottom) makes it hard to fully implement what I had in mind !
Guess I’ll settle for a more simplistic behavior for my app.
Thanks again for the component, I’m going to use it all the time :slight_smile:

Hi all (@victoryhb),

I’m building an app and wanted to have a simpler way to describe nested menu structures with this nice component. I came up with something like this below (a simple example) along with the code that runs it:

menu = {
    'title': 'Todo App',
    'items': { 
        'Home' : {
            'action': None, 'item_icon': 'house', 'submenu': {
                'title': None,
                'items': { 
                    'View Tasks' : {'action': do_view_tasks, 'item_icon': 'list-task', 'submenu': None},
                    'Manage Tasks' : {'action': do_manage_tasks, 'item_icon': 'list-check', 'submenu': None},
                    'Upload Tasks' : {'action': do_upload_tasks, 'item_icon': 'cloud-upload-fill', 'submenu': None},
                },
                'menu_icon': None,
                'default_index': 0,
                'with_view_panel': 'main',
                'orientation': 'horizontal',
                'styles': styles
            }
        },
        'Settings' : {
            'action': None, 'item_icon': 'gear', 'submenu': {
                'title': None,
                'items': { 
                    'Manage Credentials' : {'action': do_credentials, 'item_icon': 'key', 'submenu': None},
                    'View Logs' : {'action': do_logs, 'item_icon': 'journals', 'submenu': None},
                },
                'menu_icon': None,
                'default_index': 0,
                'with_view_panel': 'main',
                'orientation': 'horizontal',
                'styles': styles
            }
        }
    },
    'menu_icon': 'clipboard2-check-fill',
    'default_index': 0,
    'with_view_panel': 'sidebar',
    'orientation': 'vertical',
    'styles': styles
}

In theory this dict object could be externalized in a json file. The menu renderer, show_menu(), can be modified to consume and display the json representation. You could then display different menus depending on authorization rules, for example. In a similar vein, the menu scheme can be easily augmented with role scope attributes that the menu renderer uses to include/exclude menu options.

Hope someone finds it useful.

Arvindra

3 Likes

Copy from github issue here
Hi @victoryhb and @andfanilo and All
Thank you very much for this component, it makes my app more beautiful and user-friendly.
My streamlit-option-menu version is 0.3.2.
After I deploy my app on the server, I find a problem that I cannot overcome even I try my best to set different kind of “styles” option.(BTW, I’m not familiar with CSS).
If my app runs on the widescreen displayer, after user maximizes the webpage, the option_menu couldn’t extend the width just like the other widget, there is empty space on the left and right of the option menu , just like the following picture

Is there a parameter such as use_column_width for st.image ? or Can I just set some parameters for styles parameter?

Need your kindly suggestions.
Thanks a lot
This text will be hidden

Hi @asehmi, your solution to handle complex menu structures reminds me a similar one I came up with while trying to reduce some boilerplate code and make easier dealing with streamlit-option-menu.

Since you kindly share with us all your solution, I decided to share mine as well with same spirit :slight_smile: and thanks of course to @victoryhb for such an amazing component!

I quickly packaged my solution within a demo app: hope can be useful or inspiring for someone!

@asehmi I like your approach because it tries to standardize menu structures in a commonly used format like JSON - I took a shot with Python’s dataclasses but more or less on a similar path. And, just like in your last sentence, I also had the need to restrict some page display to a whitelist of selected users: I found that the usage of session state and auth methods suggested in the docs are just the cherry on top! :cherries:

3 Likes

@sis Nice. Good job on your solution and thanks for sharing. There are many ways to skin the cat as they say. In my solution I wanted to keep the MVC parts quite separate (M = model/representation, V = view/option-menu component, C = controller/renderer).

P.S. I couldn’t get your demo to load. Perhaps it needs restarting?

Great to see this component, the best have ever see

@asehmi got it, I didn’t know about MVC pattern (I’m just an amateur software dev :slight_smile:) but I will definitely deep dive about pros and cons, thanks!

About the demo app: it’s really strange, I checked it just now and seems to be up and running. Anyway, I tried rebooting: hope this will make it available again to everyone.

This is the error still showing in my console

Hello, @victoryhb! First of all, congrats on your creation! It’s trully amazing! I have a doubt regarding one thing: Is it possible to change the frontend menu through the backend? What happens is that after running a model training I would like to go back automatically to the home page, but I’m not able to send this to option_menu this command. It brings me the error that I’m trying to create two option menus, one with the command coming from the front end and the other coming from the backend. Thank you!

options = option_menu(“Main Menu”, [“Input Data”, “Data preparation”,“parameters”,“other”],
icons=[’ box arrow in down ', ’ wrench adjustable ‘,’ bar chart line ‘,’ map '], menu_icon=“cast”, default_index=0)
options
hello.
I use this code but when running it, the icon of options doesn’t show.
is need to do code for using bootstrap icons?

Hi @victoryhb this is a great little component, do you know if there’s a way to use this in combination with the new official multi-page feature Streamlit recently announced? Introducing multipage apps! 📄

We’d like to use this new mutli-page functionality to be able to break up the app a little more but I really like the visual styling of your options-menu (and ability to use bootstrap icons) better than the default Streamlit emoji-type menu for multi-page apps shown in the blog post above.

Have you tried it with the “-” between the words of the icon names instead of spaces? ‘box-arrow-in-down’ instead of ‘box arrow in down’

Demonstrated here.

1 Like

Perfect, thank you!!

1 Like

Is there a way to disable the entire option-menu or only some of the options within the menu (i.e. make them “not clickable”)? Maybe by using some CSS?

How can I style the menu in horizontal mode to give every option only a fixed width/just as much width as it needs instead of having the entire menu to span the whole width of the container it is placed in? (for example if you just have 2 options, the menu will create 2 large buttons across the screen width which can look weird)

Hi, when I put orientation=’ horizontal’ they not working.

Please explain.