New Component: st-copy, a new way to copy anything

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>
            ''' 

and wherever you want to use it put:

# Render iframe with copy-to-clipboard button using srcdoc
            iframe_html = self.get_copy_to_clipboard_iframe_html(text_output)
            iframe_srcdoc = iframe_html.replace('"', '&quot;').replace('\n', ' ')
            st.markdown(
                f'<iframe srcdoc="{iframe_srcdoc}" width="200" height="60" style="border:none;"></iframe>',
                unsafe_allow_html=True
            )

Of course, you may use different styling.

1 Like