Metadata-Version: 2.4
Name: st-copy-button
Version: 0.2.3
Summary: A simple Streamlit component for copying text to the user's clipboard with one click.
License: MIT
License-File: LICENSE
Keywords: streamlit,component,clipboard,copy,copy-to-clipboard
Author: James Young
Author-email: james.young@ramseysolutions.com
Requires-Python: >=3.9.8,<4.0
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Web Environment
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Software Development :: User Interfaces
Classifier: Topic :: Software Development :: Widget Sets
Classifier: Typing :: Typed
Requires-Dist: streamlit (>=1.31.0,<2.0.0)
Project-URL: Homepage, https://gitlab.com/james.young2/st-copy-button
Project-URL: Issues, https://gitlab.com/james.young2/st-copy-button/-/issues
Project-URL: Repository, https://gitlab.com/james.young2/st-copy-button
Description-Content-Type: text/markdown

# st-copy-button

A simple Streamlit component for copying text to the user's clipboard with one click.

It renders a small button styled to match your app's active Streamlit theme, in
light and dark mode alike, and reports back whether the copy succeeded.

## Installation

```sh
pip install st-copy-button
```

## Quick start

```python
import streamlit as st
from st_copy_button import st_copy_button

st_copy_button("Copy this to clipboard")
```

Use as many as you like — each button gets its own identity automatically:

```python
for name, token in tokens.items():
    st.write(name)
    st_copy_button(token)
```

Customise the labels, and optionally show the text itself as a second,
also-clickable button to the left of the copy button:

```python
st_copy_button(
    text="Custom text",
    before_copy_label="📋 Push to copy",
    after_copy_label="✅ Text copied!",
    show_text=True,
)
```

## The return value

`st_copy_button()` returns three different things, so check for `True`
explicitly rather than treating the result as a plain boolean:

| Value | Meaning |
|---|---|
| `None` | The button was not clicked on this run. |
| `True` | It was clicked and the text reached the clipboard. |
| `False` | It was clicked but the copy failed — most often because the browser withheld clipboard access (see [Requirements](#requirements)). |

```python
if st_copy_button("some text") is True:
    st.toast("Copied!")
```

Two things to know about the timing:

- **A click reruns your app.** The return value is available on that rerun, not
  in the same run as the click.
- **The value lasts exactly one run.** The run after a click reports `None`
  again, so a click won't re-fire on every subsequent rerun.

## API

```python
st_copy_button(text, before_copy_label="📋", after_copy_label="✅", show_text=False, key=None)
```

| Parameter | Type | Default | Description |
|---|---|---|---|
| `text` | `str` | *required* | The text to copy. Leading and trailing whitespace is stripped before it reaches the clipboard. |
| `before_copy_label` | `str` | `"📋"` | The label shown before a copy, and again about a second afterwards. |
| `after_copy_label` | `str` | `"✅"` | The label shown briefly after a successful copy. |
| `show_text` | `bool` | `False` | Also render `text` as a second, clickable button to the left of the copy button. |
| `key` | `str` or `None` | `None` | Identifies this button among all elements in the app. See below. |

### Keys

You usually don't need one. When `key` is omitted, a key is generated from the
line of code that called `st_copy_button`, which keeps each button distinct and
stable across reruns — including inside `@st.fragment` and behind conditionals,
since one line is one button no matter which runs execute it.

Pass an explicit key when several buttons share a **single line**, a loop being
the usual case, so that changing how many there are — or the order they run in
— doesn't renumber them:

```python
for row in rows:
    st_copy_button(row.token, key=f"token_{row.id}")
```

Keys must be unique across your whole app, the same as any other Streamlit
element key.

## Requirements

Browsers only expose the clipboard API in a [secure
context](https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts):
HTTPS, or `localhost`. On an app served over plain HTTP from anything else — a
LAN address, a container IP, a reverse proxy without TLS — the copy will fail
and the button currently gives no visible sign of it. The call still returns
`False`, so you can surface it yourself:

```python
if st_copy_button(text) is False:
    st.warning("Couldn't reach the clipboard — copy the text manually.")
```

Requires Python 3.9.8+ and Streamlit 1.31+.

## Development

```sh
poetry install                                       # Python dependencies
cd st_copy_button/frontend && npm install && npm run build   # compile the frontend
poetry run streamlit run st_copy_button/example.py   # run the demo app
```

The frontend build output is gitignored but is packaged into the wheel, so a
fresh `npm run build` is needed before `poetry build`.

To work on the frontend with hot reloading, set `_RELEASE = False` in
`st_copy_button/__init__.py` and run `npm start` (port 3001) alongside the app.

Tests are Playwright end-to-end tests that drive a live Streamlit instance:

```sh
poetry run playwright install chromium   # once
poetry run pytest e2e/
```

## License

MIT. This project contains portions derived from
[st-copy-to-clipboard](https://github.com/mmz-001/st-copy-to-clipboard) by
Sasmitha Manathunga, whose copyright and MIT terms are preserved in
[LICENSE](LICENSE).

