St.radio() split into parts, accepting dictionary as input

Problem

A use case I have is to present the user a set of models they can access (typically in the sidebar with radio buttons), but to separate the models into groups falling under different categories. In the example below, the user should be able to select Page 3, and leave Page 1 and Page 2 unselected. This is common navigation in documentation or blogs.

Category 1

  • Page 1
  • Page 2

Category 2

  • Page 3
  • Page 4

Although you can make two separate Streamlit radio inputs now, you can’t enforce that only one is selected at any one time (both will need to have a selection).

Solution

Allowing st.radio() to accept a dictionary as input could be a neat way to achieve this, without affecting the basic radio feature:

dictionary = {'Category 1': ['Page 1, Page 2], 'Category 2': ['Page 3, Page 4]}
selection = st.radio("label", dictionary, index=(1,0))

Selection returns a tuple: (‘Category 1’, ‘Page 3’) or just ‘Page 3’, not sure what is best… Both work for my case.

Alternatively, one could allow the simple radio button feature to have no selection. Then when selecting Page 3, the value in Category 1 could be removed. This is not my preferred approach.

Additional context

I already posted this feature proposal to GitHub

1 Like

Hey @kierancondon!

While the Streamlit team is figuring out if your proposal would fit their plans, I think that’s a good idea for a custom component so I put it in the tracker for grabs :slight_smile: (though it wouldn’t work in the sidebar).

With our current building blocks, though it goes against your wish I would separate each section in a selectbox. I understand you wouldn’t be able to see all of the pages at once + whenever you change section, one of the pages would be autoamtically selected and displayed unless you use an empty first placeholder item, but it enforces only one page is selected at a time.

import streamlit as st

dictionary = {'Classification': ['Linear', 'Tree'], 'Regression': ['Logistic', 'Random']}

st.title("Choose your ML model")

selected_section = st.sidebar.selectbox("Choose section:", sorted(dictionary.keys()))
selected_page = st.sidebar.radio("Choose page:", sorted(dictionary[selected_section]))

if st.button("Run model"):
    st.write(f"Running {selected_section}:{selected_page}")

test

Cheers,
Fanilo

1 Like