New Component: Button Group

Hello everyone,

I created an Streamlit implementation of the BaseUI Button Group ( baseweb.design/components/button-group/).

My main motivation was to be able to use FontAweseome Icons in Button Labels. Furthermore, it was important to me that I can align the buttons easily left, right, center.

GitHub: flucas96/st_btn_group (github.com)
PyPI: st-btn-group · PyPI
Example app: Streamlit Button Group Component · Streamlit (st-btn-group.streamlit.app)

Primarily, I use these buttons as download buttons. In this mode, they do not return a value and the page does not refresh. The return of a value can be controlled by the return_value parameter.

Some examples:

Button with FontAwesome Icon:
image

ButtonGroup with 3 Buttons:
image

Custom CSS Styling:

Example 1:
image

Example 2:
image

One thing to note:
The buttons offer three distinct modes, which can be configured through the mode parameter.

  • Default: Acts like a normal button, but unlike Streamlit Buttons, these buttons maintain their value after script re-execution.
  • Radio: Functions as a radio button, where only one button remains active at any given time.
  • Checkbox: Works like a checkbox, enabling the toggling of multiple buttons concurrently.

Maybe someone else will find this useful.

Best regards
Fabian

6 Likes

Hi @Tian,

Awesome, thanks for sharing! :clap:t5:

1 Like

Hey @Tian,
I have started using your component and I want to ask you if it is possible to return the ‘value’ from the buttons dictionary instead of the index/position of the button that is being clicked on.

My case:

type_options = [{"label": "Bruto",
                     "value": "bruto"},
                    {"label": "Neto",
                     "value": "net"}]
    btn_type=st_btn_group(buttons=type_options,
                          mode='radio',
                 key="btn-venta-GN",
                 shape='default',
                 size='default',
                 align ='left',
                 disabled = False,
                 merge_buttons = True,
                 gap_between_buttons = 0,
                 display_divider = False,
                 return_value = True)

Returns:
image

In my use case I would like the returned value to be ‘bruto’ instead of 0.

TIA

1 Like

Hi @pablochaure,

I have updated the component to have that behaviour:

You can download the latest version here:

st-btn-group · PyPI

Please let me know if it works for you!

Best regards
Tian

Yes!! It works for my use case, thanks for such quick work Tian.

Moreover, would it be hard to implement a default (preselected) value when the mode=‘radio’?

Hi @pablochaure,

I have added the parameter radio_default_index which takes in the index of the button that should be selected by default.

For instance when displaying these buttons:

buttons = [
    {   "label": "Button 1",
        "value": "1",
    },
    {   "label": "Button 2",
        "value": "2",
    },
    {   "label": "Button 3",
        "value": "3",
    },
    {   "label": "Button 4",
        "value": "4",},
    {   "label": "Button 5",
        "value": "5",}
]

Setting radio_default_index = 1 would preselect Button 2 which means that the component return the value of Button 2 which is 2.

You can download the updated version here:

st-btn-group · PyPI

Best regards
Fabian

Hey @Tian,

I am having trouble downloading the updated version.

ERROR: st-btn-group has an invalid wheel, st-btn-group has an invalid wheel, multiple .dist-info directories found: st_btn_group-0.0.10.dist-info, st_btn_group-0.0.9.dist-info

Is this something on my end or maybe an issue when uploading to pypi?

Hi @pablochaure,

I have uploaded it again with a new version. The installation seems to work for me now.


pip install st-btn-group==0.0.11

Best regards
Tian

Hey there @Tian,

Everything is working for me and those new features make the component great for my use case.

Thanks for your contribution!

Regards,

Pablo

1 Like

Glad to hear that you like it!

Hello,

First of all thank you for your contribution and congratulations for doing such a useful component.

I have been playing with it, and works nicely.

My question is, Is it possible to use it in an streamlit empty()? How?

#I have been checking it and it's possible using
placeholder = st.empty()
with placeholder.container():
    buttons_selection = st_btn_group(...)

Thanks!

2 Likes

Hi @anigmo,

great that you found a solution!

Best regards
Fabian

@Tian Hey, thanks a lot for this contribution!
I am using this in a chat bot (st.chat_input, st.chat_message) to show a like/dislike option after each response. The issue is, as soon as it reaches the code block for st_btn_group, the app reruns multiple times, that makes it very glitchy. Is there any possible solution for this?

Here I am attaching the code I’m using -

buttons = [
  {"label": "👍",
   "value": "like",
   "style": {"border-radius": "22px", "padding": "1px"}
   },
  {"label": "👎",
   "value": "dislike",
   "style": {"border-radius": "22px", "padding": "1px"}
   }
]

col = st.columns([92, 8])
with col[1]:
  returned = st_btn_group(buttons=buttons, key=message["query_id"], mode='radio',
                          return_value=True)

Here if you try to store “returned” into a list, it will return “like” or “dislike” multiple times for 1 question.
How do I avoid rerunning?

Thanks in advance!

1 Like

Hey @Tian, thankyou for the solution. I have the case where I need to have st.rerun() once the button is clicked, but in your case the program runs in endless loop. Would it be possible to modify in a way that it behaves as st.button() so that it won’t go in a loop.
The following block creates a problem,

if st_btn_group(
    buttons=[{"label": "<i class='fas fa-home'></i>", "value":"home"}],
    group_style= {"margin-bottom":"22px"}   
):
    st.write("clicked")
    print("clicked")
    st.rerun()

while, the following seems working fine.

if st.button("abc"):
    st.write("clicked")
    print("clicked")
    st.rerun()

Thank you for your time!

Regards,
Nimesh

Thanks a lot @Tian , Is there a way to customise the color after clicking a radio button? (I am fairly new to programming so I might have missed it.)

Kind regards,
Laurenz