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

Happy new year everyone!
I discovered Streamlit a couple of weeks ago and fell in love with it immediately. To help myself learn how to make custom components, I created streamlit-option-menu, whose functions, though very simple, are not found in existing components. Hopefully it can be of use to someone else as well!

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

It is similar in function to st.selectbox(), except that:

  • It uses a simple static list to display the options instead of a dropdown

  • It has configurable icons for each option item and the menu title

It is built on streamlit-component-template-vue, styled with Bootstrap and with icons from bootstrap-icons.

Installation

pip install streamlit-option-menu

Parameters

The option_menu function accepts the following parameters:

  • menu_title (required): the title of the menu
  • options (required): the array of (string) options to display in the menu
  • default_index (optional, default=0): the index of the selected option by default
  • menu_icon (optional, default=“menu-up”): name of the bootstrap-icon to be used for the menu title
  • icons (optional, default=[“caret-right”]): array of bootstrap-icon names to be used for each option; its length should be equal to the length of options;
    The function returns the (string) option currently selected

Example

import streamlit as st
from streamlit_option_menu import option_menu

with st.sidebar:
    selected = option_menu("Main Menu", ["Home", 'Settings'], 
        icons=['house', 'gear'], menu_icon="cast", default_index=1)
    selected
44 Likes

Hello @victoryhb, welcome to the community, and what a beautiful way to start the new year :smiley: it’s very pretty!

Can you add it to the community tracker so we don’t lose track of it?

EDIT: also it’s in Vue.js?! That’s absolutely awesome :heart_eyes: have you had any problems dealing with the Vue.js way of building components?

Happy Streamlitin’
Fanilo :balloon:

5 Likes

Great work @victoryhb !

1 Like

Thank you for your kind words! I want to express my special thanks to you because my simple component is based on your excellent Vue.js template! Without your work, I wouldn’t have attempted to build the component (since I am not familiar with React). Your template makes building Vue components very easy since much of the code is self-explanatory. I did run into some problems initially with understanding the code in setup(), because I haven’t touched Vue for a while and this is the first time I deal with Vue 3 syntax. But other than that, everything was quite smooth and building the component only took a couple of hours.
P.S. I don’t seem to be able to add my component to the community tracker, perhaps because I haven’t reached the required trust level yet?

6 Likes

Thank you for your nice words :grinning_face_with_smiling_eyes:!

Awesome piece of work !!!

Thank you! :grin:

Great work

2 Likes

When there is too much option, does it get longer or is there a scroll bar? I have an app with 17 page, so I am looking for something that might work instead of selectbox

1 Like

This is super cool! I just installed and added it to an app of mine. It doesn’t play nicely with dark mode unfortunately, is that something you plan on adding at some point?

1 Like

It gets longer and a scrollbar will appear when it overflows its container (similar to the default CSS overflow behavior), but it might not work well with very long lists.

The component is using the theme color settings from streamlit, which you can customize yourself. May I ask what problems you have encountered?

The text for the menu title and icon do not seem to be connected to color settings. Everything else adjusts correctly, but that one stays black/gray.

1 Like

That is indeed a bug! Just fixed it in the latest published version (0.2.5). Thanks for reporting :grinning_face_with_smiling_eyes:

2 Likes

You’re the best! Appreciate the quick fix!

1 Like

These are the type of add-ons I’m looking for! Just like Hydralit it adds a nice looking way of multi-page Streamlit apps instead of a dropdown or hacky looking radio buttons.

I did find a little visual bug when using it on mobile(Chrome browser) but I think this is a Streamlit related issue rather than the option-menu component(I remember running into it half a year ago).
The closing X seems to move out of sight when selecting a different option:

Maybe you can reproduce it with my code:

import streamlit as st
from streamlit_option_menu import option_menu

with st.sidebar:
    selected = option_menu("Menu", ["Home", 'Settings'], 
        icons=['house', 'gear'], default_index=0)

if selected == "Home":
    st.write("home is where the heart is")
else:
    st.write("settings is my bettings")
1 Like

Hi @Fhireman, thanks for the message. Unfortunately I haven’t been able to reproduce the bug you described on Chrome on my iPhone (using the code you provided). As you said, it probably is a streamlit bug, appearing in certain mobile (Android?) versions of the Chrome browser. Perhaps you could file an issue in the Streamlit repo?

2 Likes

Hi :slight_smile: thanks for trying though!
I can’t remember if I did back then since I usually file an issue when I encounter such things but I’ll check it out.

The thing I do remember is that back then the person testing it couldn’t reproduce the behavior but turned out they deployed the app to Streamlit Sharing for testing it. Once they also tried to connect their phone to their locally running Streamlit app they encountered the bug as well.

But maybe it’s indeed an Android Chrome thing, I’ll check it out and will report it if I can’t find an item related to it!

2 Likes

This is a really nice component @victoryhb. Thanks for making it! Already thinking about ways to use it. Do you think it would be possible to layout these options out horizontally? My use case is the image below. I want to expand that selectbox into a statically-displayed option menu.

3 Likes

Hi @ryanlampkin, thanks for the message. It is actually quite trivial to add the new orientation, and since I am in the mood, why not! :grin:

Please update the component to the latest version (0.2.7) and try the following:

# horizontal menu
selected2 = option_menu(None, ["Home", "Upload", "Tasks", 'Settings'], 
    icons=['house', 'cloud-upload', "list-task", 'gear'], 
    menu_icon="cast", default_index=0, orientation="horizontal")
    selected2

5 Likes