Streamlit chat_message add edit/delete inline messages

Hello, streamlit community!
I needed some assistance, I am attempting to add chat buttons right next to the chat_message conversation as shown below. it seems to be working well currently but I’m concerned it might be a bit hacky? and there is a better approach that I don’t know.

import streamlit as st

temp = [
    {"name": "user", "msg": "Ping"},
    {"name": "assistant", "msg": "Pong"},
    {"name": "user", "msg": "Can you help me with a Python script?"},
    {"name": "assistant", "msg": "Of course! What do you need help with?"},
    {"name": "user", "msg": "I need to sort a list of dictionaries by a key."},
    {"name": "assistant",
     "msg": "Here’s a sample code snippet to do that:\n\n```python\nlist_of_dicts = [{'name': 'Alice', 'age': 30}, "
            "{'name': 'Bob', 'age': 25}]\n\nsorted_list = sorted(list_of_dicts, key=lambda x: x['age'])\nprint("
            "sorted_list)\n```"},
    {"name": "user", "msg": "Explain the difference between a list and a tuple in Python."},
    {"name": "assistant",
     "msg": "A list is mutable, meaning you can change its contents after it’s created, while a tuple is immutable, "
            "so its contents cannot be modified after creation. Lists are defined with square brackets `[]` and "
            "tuples with parentheses `()`. For example:\n\n```python\nmy_list = [1, 2, 3]\nmy_tuple = (1, 2, 3)\n```"},
    {"name": "user", "msg": "Write a short poem about autumn."},
    {"name": "assistant",
     "msg": "Here’s a little poem for you:\n\n**Autumn Whispers**\nLeaves in golden hues descend,\nCrisp and cool, "
            "the breezes send.\nPumpkin patches, apple spice,\nAutumn’s charm, a sweet delight."},
    {"name": "user", "msg": "What’s the capital of France?"},
    {"name": "assistant", "msg": "The capital of France is Paris."},
]

st.markdown("""
    <style>
    .stButton>button {
        background-color: rgba(0, 123, 255, 0.0); /* Blue background with 50% opacity */
        position: relative; /* Positioning context */
        padding: 0px 0px;
        min-width: 33px;
        min-height: 31px;
        left: -40px; /* Move the button to the left */
        opacity: 0; /* Fully invisible */
    }
    .stButton>button:hover {
        opacity: 1; /* Make visible on hover */
    }
    </style>
""", unsafe_allow_html=True)

parent = st.container()
with parent:
    for val, item in enumerate(temp, start=1):
        name = item["name"]
        message = item["msg"]
        with st.container():
            col1, col2, col3 = st.columns([8, 1, 1])
            with col1:
                st.chat_message(name).write(message)
            if name == "user":
                with col2:
                    st.chat_message(name, avatar=":material/edit:").button("", key=val)
                with col3:
                    st.chat_message(name, avatar=":material/delete:").button("", key=-val)

here’s my approach/thought process:

  • Initially I tried to add buttons right next to messages, and the formatting kept messing up. without using a column format
  • I tried making CSS buttons but the interactions between CSS and streamlit just would not work no matter how much I tried.
  • After adding the column format the buttons were too big and would mess up the CSS again as more messages came through, so I switched to adding a container across one row and that fixed it.
  • the hacky part is having a “button” that’s see-through but actually, it’s on top of the material icons giving the illusion that the icons are buttons.

Hi! I was trying to do something similar and found your question. Did you use an alternate route or did this suffice? Does this cause any issues down the line?

I resorted to dropping edit, but delete still works. Couldn’t find a good UX to make the edit work out of the box, if you figure it out let me know!

here is my final result:
github.com/shiv248/Streamlit-x-LangGraph-Cookbooks/blob/master/msg_manipulation/app.py

Streamlit 1.39 allows material icons in buttons.

Thank you! This helps :slight_smile:

Thanks!