A Streamlit component that brings the power of AnyWidget to Streamlit applications. Create and use custom interactive widgets directly in your Streamlit apps without iframe limitations.
- Full AnyWidget Compatibility: Works with both class-based and module-based widget formats
- Custom Styling: Apply CSS to your widgets for beautiful integration with Streamlit
- Bidirectional Communication: State updates flow seamlessly between Python and JavaScript
- Simple API: Familiar interface for AnyWidget users
Streamlit-AnyWidget is distributed via PyPI.
pip install streamlit-anywidget
Requires:
- streamlit >= 0.63
- anywidget
import streamlit as st
from streamlit_anywidget import anywidget
from anywidget import AnyWidget
import traitlets
# Create a simple counter widget
class CounterWidget(AnyWidget):
value = traitlets.Int(0).tag(sync=True)
_esm = """
function render({ model, el }) {
// Create function to get current value from model
let count = () => model.get("value");
// Create button element
let btn = document.createElement("button");
btn.classList.add("counter-button");
btn.innerHTML = `Module-based Counter: ${count()}`;
// Handle click event
btn.addEventListener("click", () => {
model.set("value", count() + 1);
model.save_changes();
// Update UI immediately
btn.innerHTML = `Module-based Counter: ${count()}`;
});
// Listen for changes from Python
model.on("change:value", () => {
console.log("Value changed to:", count());
btn.innerHTML = `Module-based Counter: ${count()}`;
});
// Add to DOM
el.appendChild(btn);
}
export default { render };
"""
_css = """
.counter-button {
background-image: linear-gradient(to right, #a1c4fd, #c2e9fb);
border: 0;
border-radius: 10px;
padding: 10px 50px;
color: black;
font-weight: bold;
cursor: pointer;
}
.counter-button:hover {
background-image: linear-gradient(to right, #c2e9fb, #a1c4fd);
}
"""
# Display the widget in Streamlit
st.title("Counter Widget Example")
counter = CounterWidget()
counter_state = anywidget(counter, key="counter")
# Interact with the widget state
st.write(f"Current value: {counter.value}")
# Show debug info
with st.expander("Module Counter Debug Info"):
st.write("Module-based Counter State:", counter_state)
st.json({
"module_counter_value": counter.value
})
A simple counter widget showcasing basic interactivity.
Sync text input between Streamlit and a custom text widget.
Using the module-based format for more complex widgets.
To see all available widgets in action, run:
streamlit run examples.py
Streamlit-AnyWidget creates a bridge between Streamlit's component system and AnyWidget:
- Widget Definition: Define your widget in Python with AnyWidget
- Streamlit Integration: Use the
anywidget()
function to render it in Streamlit - State Synchronization: Changes in either Python or JavaScript automatically sync
Renders an AnyWidget instance within Streamlit.
Parameters:
widget_instance
: An AnyWidget instancekey
: Optional unique key for the component (string)
Returns:
- Dictionary containing the current widget state
- Custom Controls: Create specialized UI controls tailored to your data
- Interactive Visualizations: Build charts and graphs with interactive elements
- Form Elements: Design custom form inputs with validation and feedback
- Games & Demos: Create interactive demos and simple games
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature
) - Commit your changes (
git commit -m 'Add some amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - Open a Pull Request
Distributed under the MIT License. See LICENSE
file for more information.