I have a small problem in my application. I am currently working on a Streamlit app where I generate text via OpenAI. This text is displayed in a textarea for the user, and the textarea has a live byte counter. First, I tried creating the textarea using components.html: My code: def html_text_area_with_live_byte_counter(label, default_value, key, height=150, max_bytes=2000): html_code = f""" <div style="font-family: Arial, sans-serif;"> <label for="{key}" style="font-weight: bold;">{label}</label><br> <textarea id="{key}" style=" width: 100%; height: {height}px; font-size: 16px; background-color: #f0f0f0; font-family: 'Helvetica Neue', sans-serif; line-height: 1.5; letter-spacing: 0.5px; padding: 10px; border: 1px solid #ccc; border-radius: 4px; color: #333; ">{default_value}</textarea> <div id="{key}_counterContainer" style="margin-top: 10px;"> <strong>Byte-Zähler:</strong> <span id="{key}_byteCount">0</span> Bytes von {max_bytes} </div> </div> <script> (function() {{ const textarea = document.getElementById("{key}"); const byteCountSpan = document.getElementById("{key}_byteCount"); const counterContainer = document.getElementById("{key}_counterContainer"); const maxBytes = {max_bytes}; function updateByteCount() {{ const encoder = new TextEncoder(); const byteCount = encoder.encode(textarea.value).length; byteCountSpan.innerText = byteCount; // Ändert die Farbe des gesamten Byte-Zähler-Textes, wenn der Wert überschritten wird if (byteCount > maxBytes) {{ counterContainer.style.color = "red"; }} else {{ counterContainer.style.color = "inherit"; }} }} textarea.addEventListener("input", updateByteCount); updateByteCount(); }})(); </script> """ components.html(html_code, height=height + 100, scrolling=False) With this approach, the byte counter updates live while the user types. The problem: I also have a download button that lets the user save the textarea content as a .txt file. If I use the HTML component, I can’t grab the updated text, only the original default value. So I switched to a standard Streamlit st.text_area: def text_area_with_live_byte_counter(label: str, key: str, default: str = "", height: int = 400, max_bytes: int | None = None) -> str: # nur beim ersten Mal mit Default befüllen if key not in st.session_state: st.session_state[key] = default st.text_area(label, key=key, height=height) val = st.session_state[key] count = len(val.encode("utf-8")) over = max_bytes is not None and count > max_bytes st.markdown( f'<div style="margin-top:-6px;color:{ "red" if over else "inherit" }">' f'<strong>Byte-Zähler:</strong> {count} Bytes{f" von {max_bytes}" if max_bytes else ""}' f'</div>', unsafe_allow_html=True ) return val Here the counter only updates after the user leaves the textarea. I know that Streamlit’s textarea is static, but isn’t there a way to make the byte counter update live while typing? So in the end, I need a textarea with a live byte counter that can also be accessed by Streamlit in order to generate a download button from its content. This is my first question ever asked here, so if more information is needed, I’ll be happy to provide anything necessary to help find a solution. Continue reading...