Using HTML in widget labels (e.g., FontAwesome icons + st.button)

I made this solution, without creating a new component, according to this discussion

import streamlit as st
import streamlit.components.v1 as components
import json 

key_dict = {}
st.write('<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.0/css/all.min.css"/>', unsafe_allow_html=True)

def generate_key(icon, button_key):
    key_dict[button_key] = icon
    return {'label':button_key,'key':button_key}

st.button(**generate_key('<i class="fa-solid fa-circle-user fa-bounce"></i>',button_key = 'button_test_1'))
st.button(**generate_key('<i class="fa-brands fa-youtube fa-spin-pulse"></i>',button_key = 'button_test_2'))
st.button('test')

icon_config = f"""
        <script>
            var elements = window.parent.document.getElementsByClassName('css-x78sv8 eqr7zpz4');
            let dict = {json.dumps(key_dict)};
            let keys = Object.keys(dict);
            let icons = Object.values(dict);
            for (var i = 0; i < elements.length; ++i) {{
                for (var j = 0; j < keys.length; ++j){{
                    if (elements[i].innerText == keys[j])
                    elements[i].innerHTML = icons[j];
                }}
            }}
        </script>
        """
components.html(f"{icon_config}", height=0, width=0)

The idea is to first generate a button with a unique key, then search for it and replace its content with the icon

1 Like