How to achieving dynamic image functionality where an image changes based on user interaction in a Streamlit application

When the search bar is empty, the arrow icon in the right corner is grey (1st Image). As the user begins to type in the search bar, the arrow icon turns blue (2nd Image).


There is a lot of fiddling to do to make it look good, but here’s one way that seems to achieve roughly what you want

import streamlit as st

name = st.text_input("Enter your name: ", key="name")

if not name:
    st.markdown(
        """
    <style>
    div[data-baseweb="base-input"]::after {
        content: "";
        position: absolute;
        right: 5px; /* Adjust based on desired position */
        top: 67%;
        transform: translateY(-50%);
        width: 30px; /* Match the size of your SVG */
        height: 34px;
        background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='currentColor'%3E%3Cpath d='M3.5 1.34558C3.58425 1.34558 3.66714 1.36687 3.74096 1.40747L22.2034 11.5618C22.4454 11.6949 22.5337 11.9989 22.4006 12.2409C22.3549 12.324 22.2865 12.3924 22.2034 12.4381L3.74096 22.5924C3.499 22.7255 3.19497 22.6372 3.06189 22.3953C3.02129 22.3214 3 22.2386 3 22.1543V1.84558C3 1.56944 3.22386 1.34558 3.5 1.34558ZM5 4.38249V10.9999H10V12.9999H5V19.6174L18.8499 11.9999L5 4.38249Z'%3E%3C/path%3E%3C/svg%3E");
        background-size: 30px;
        background-repeat: no-repeat;
    }
    </style>
                """,
        unsafe_allow_html=True,
    )

else:
    st.markdown(
        """
    <style>
    div[data-baseweb="base-input"]::after {
        content: "";
        position: absolute;
        right: 5px; /* Adjust based on desired position */
        top: 67%;
        transform: translateY(-50%);
        width: 30px; /* Match the size of your SVG */
        height: 34px;
        border: 2px solid blue; /* Blue border */
        border-radius: 4px; /* Optional: for rounded corners */
        background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='white'%3E%3Cpath d='M3.5 1.34558C3.58425 1.34558 3.66714 1.36687 3.74096 1.40747L22.2034 11.5618C22.4454 11.6949 22.5337 11.9989 22.4006 12.2409C22.3549 12.324 22.2865 12.3924 22.2034 12.4381L3.74096 22.5924C3.499 22.7255 3.19497 22.6372 3.06189 22.3953C3.02129 22.3214 3 22.2386 3 22.1543V1.84558C3 1.56944 3.22386 1.34558 3.5 1.34558ZM5 4.38249V10.9999H10V12.9999H5V19.6174L18.8499 11.9999L5 4.38249Z'%3E%3C/path%3E%3C/svg%3E");
        background-size: 30px;
        background-color: blue;
        background-repeat: no-repeat;
    }
    </style>

                """,
        unsafe_allow_html=True,
    )

@blackary Thanks for your response. Could you suggest another alternative as well? While the current solution functions adequately, it doesn’t fully meet my expectations. For instance, the arrow turns blue only after pressing Enter, but I would prefer the arrow to change color as soon as I begin typing.

You might be able to get that behavior using GitHub - blackary/streamlit-keyup: Streamlit text input that returns value on keyup, but it would require different CSS to properly target the text input.

1 Like

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.