How to display selectbox inline

I am working on a streamlit app to let users accept or reject the NER tags generated from a model. I want the selectbox to be displayed next to the tags within the text, as shown in the screenshot below:

Any advice on how to implement this using st.selectbox() would be greatly appreciated.

That is way beyon the standard layout capabilities that streamlit offers. I gues you could create a custom component, though.

1 Like

If you are not looking for that exact same look, you could cycle through columns while writing pairs of st.markdown and st.selectbox in a couple of nested columns. Here’s an example using stanza:

Check it out at Community Cloud here

Code:
import streamlit as st
import stanza
from itertools import cycle
from collections import namedtuple

st.set_page_config(layout="wide")

## Coloring settings
Color = namedtuple("Color", ["bg", "c"])
formatting = {
    "B" : Color(bg="#FF000050", c="red"),
    "O" : Color(bg="#EE82EE50", c="violet"),
    "I" : Color(bg="#FFA50050", c="orange"),
    "E" : Color(bg="#0000FF50", c="blue"),
    "S" : Color(bg="#00FF0050", c="green"),
}

def color_tag(token):
    """
    Returns a colored token text and NER
    """
    first_letter = token.ner[0]
    colors = formatting.get(first_letter, None)

    if colors:
        return f"""<mark style="background-color: {colors.bg};">{token.text}</mark><br> :{colors.c}[{token.ner}]"""
    else:
        return f"""{token.text}\n{token.ner}"""

@st.cache_data
def process_text(text:str):
    nlp = stanza.Pipeline(lang='en', processors='tokenize,ner')
    doc = nlp(text)
    return doc

"## πŸ’¬ Text analysis tokenization and NER"

with st.form("Submit text for analysis:"):
    
    text = st.text_area(
        "Input text:", 
        value="Chris Manning teaches at Stanford University. He lives in the Bay Area.",
        max_chars=1_000)
    
    submit_button = st.form_submit_button("Submit")

doc = process_text(text)
options = ["Undecided", "Decided"]

if submit_button:
    
    "****"
    "### πŸ“— Results:"

    for i, sentence in enumerate(doc.sentences, start=1):
        
        with st.expander(f"Sentence {i}: **{sentence.text}**"):

            main_cols = st.columns(3)
            cycle_cols = cycle(main_cols)

            for col, (j, token) in zip(cycle_cols, enumerate(sentence.tokens)):
                with col:
                    cols = st.columns([1,1.5])
                    with cols[0]: 
                        st.markdown(color_tag(token), unsafe_allow_html=True)
                    with cols[1]: st.selectbox(f"Selectbox_{i},{j}", options=options, label_visibility="collapsed")
1 Like

Hi edsaac, thank you very much for sharing a working example of presenting a tag and select box in two columns. The end-users prefer the look in my screenshot because it allows them to easily read the whole sentence and determine whether to accept or reject the tag.