Custom Jupyter widgets made easy with modern web technologies and seamless platform integration
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
The AnyWidget class provides the fundamental building blocks for creating custom Jupyter widgets with ES modules and CSS styling. It handles the Jupyter widget protocol, communication setup, and platform-specific optimizations.
The main class for creating custom Jupyter widgets that inherit from ipywidgets.DOMWidget with enhanced ES module and CSS support.
class AnyWidget(ipywidgets.DOMWidget):
"""
Main AnyWidget base class for creating custom Jupyter widgets.
Attributes:
_model_name (str): Widget model name ("AnyModel")
_model_module (str): Widget model module ("anywidget")
_model_module_version (str): Widget model version
_view_name (str): Widget view name ("AnyView")
_view_module (str): Widget view module ("anywidget")
_view_module_version (str): Widget view version
"""
def __init__(*args, **kwargs):
"""
Initialize the widget with ES module and CSS traits.
Automatically sets up:
- ES module trait from _esm class attribute
- CSS trait from _css class attribute
- Unique widget ID for identification
- Google Colab compatibility if needed
- Command registration for custom messages
Parameters:
*args: Positional arguments passed to parent
**kwargs: Keyword arguments passed to parent
"""
def __init_subclass__(**kwargs):
"""
Class method called when AnyWidget is subclassed.
Automatically processes:
- _esm attribute: converts file paths to FileContents objects
- _css attribute: converts file paths to FileContents objects
Parameters:
**kwargs: Keyword arguments from class definition
"""
def _repr_mimebundle_(**kwargs):
"""
Generate MIME bundle representation for Jupyter display.
Returns widget representation with communication channel ID
for rendering in Jupyter environments.
Parameters:
**kwargs: Display formatting options (include/exclude)
Returns:
tuple[dict, dict] | None: MIME bundle data and metadata
"""Key attributes that define widget behavior and appearance.
# Class attributes for ES module and CSS
_esm: str | Path | FileContents | VirtualFileContents
"""ES Module code or file path for widget frontend"""
_css: str | Path | FileContents | VirtualFileContents
"""CSS styles or file path for widget styling"""
# Traitlets for Jupyter communication
_model_name: Unicode
"""Widget model name synced with frontend"""
_model_module: Unicode
"""Widget model module synced with frontend"""
_model_module_version: Unicode
"""Widget model version synced with frontend"""
_view_name: Unicode
"""Widget view name synced with frontend"""
_view_module: Unicode
"""Widget view module synced with frontend"""
_view_module_version: Unicode
"""Widget view version synced with frontend"""import anywidget
import traitlets as t
class SimpleWidget(anywidget.AnyWidget):
_esm = """
function render({ model, el }) {
el.innerHTML = "<h1>Hello, World!</h1>";
}
export default { render };
"""
value = t.Unicode("Hello").tag(sync=True)
widget = SimpleWidget()
widget # Displays in Jupyterimport anywidget
import traitlets as t
class FileBasedWidget(anywidget.AnyWidget):
_esm = "./widget.js" # File path to ES module
_css = "./widget.css" # File path to CSS styles
data = t.List([]).tag(sync=True)
# Files are automatically watched for changes during development
widget = FileBasedWidget(data=[1, 2, 3, 4, 5])import anywidget
import traitlets as t
class CounterWidget(anywidget.AnyWidget):
_esm = """
function render({ model, el }) {
let count = () => model.get("value");
let btn = document.createElement("button");
btn.innerHTML = `Count: ${count()}`;
btn.addEventListener("click", () => {
model.set("value", count() + 1);
});
model.on("change:value", () => {
btn.innerHTML = `Count: ${count()}`;
});
el.appendChild(btn);
}
export default { render };
"""
value = t.Int(0).tag(sync=True)
step = t.Int(1).tag(sync=True)
# Create widget with custom initial state
counter = CounterWidget(value=10, step=2)Install with Tessl CLI
npx tessl i tessl/pypi-anywidget