I’m excited to introduce st-copy, a new Streamlit component that adds a customizable “copy to clipboard” button to your apps.
What is st-copy?
st-copy allows you to add a copy button to any text content in your Streamlit app. It’s especially useful for copying code snippets, messages, or any other text, enhancing user interaction.
Features
Streamlit theme aware: Adapts icon colour & tooltip style automatically; works in both light and dark themes.
Two icon styles: Google Material Symbols (default) or the native Streamlit code‑block icon.
Custom tooltip & “Copied!” label: Localised UI in one line.
Keyboard‑friendly: Fully focusable, press Enter/Space to copy.
Installation
pip install st-copy
Example Usage
from st_copy import copy_button
copy_button(
"Text to copy",
tooltip="Copy this text",
copied_label="Copied!",
icon="st",
)
I have created another solution that does not require React.
It is based on the iframe implementation found here: It Works! Custom "Copy to Clipboard" Buttons 😎 with the only difference that it uses srcdoc instead of src so it does not require serving a static html page from the same domain.
Add this function to the server code:
def get_copy_to_clipboard_iframe_html(self, text_to_copy: str) -> str:
"""
Returns HTML for an iframe with a copy-to-clipboard button, using srcdoc.
The text to copy is embedded directly in the HTML.
Args:
text_to_copy: The string to be copied to clipboard.
Returns:
HTML string for use as iframe srcdoc.
"""
import html
# Escape for HTML attribute and JS string
safe_text = html.escape(text_to_copy, quote=True).replace("'", "'")
# Also escape for JS string (double quotes)
safe_text_js = safe_text.replace('"', '\\"')
return f'''
<html>
<head>
<meta charset=\"UTF-8\">
<title>Copy Text to Clipboard</title>
<meta http-equiv=\"Content-Security-Policy\" content=\"frame-ancestors 'self' *\">
<style>
#copyButton {{
transition: opacity 1s;
padding: 10px;
font-size: 16px;
border-radius: 8px;
background-color: #f0f0f0;
border: 1px solid #ccc;
cursor: pointer;
font-family: "Source Sans Pro", sans-serif;
}}
#copyButton:hover {{
background-color: #e0e0e0;
}}
</style>
</head>
<body>
<input type=\"text\" id=\"textToCopy\" value=\"{safe_text}\" style=\"position: absolute; left: -9999px;\">
<button id=\"copyButton\" onclick=\"copyToClipboard()\">📋 Copy to clipboard</button>
<script>
const textToCopy = document.getElementById('textToCopy');
const copyButton = document.getElementById('copyButton');
copyButton.title = textToCopy.value;
function copyToClipboard() {{
textToCopy.select();
document.execCommand('copy');
copyButton.textContent = '✔';
setTimeout(function () {{
copyButton.textContent = '📋';
copyButton.title = textToCopy.value;
}}, 1000);
}}
</script>
</body>
</html>
'''
Really good job! The formatting of the output is also super nice. For future works, would it be possible to also have a option for a text button for the target groups, who are not so familiar with icons?