Skip to content

Display parts of your ipywidgets or solara app in separate browser windows

License

Notifications You must be signed in to change notification settings

widgetti/ipypopout

Repository files navigation

Ipypopout

Version

Use Ipypopout to display parts of your ipywidgets or solara app in separate browser windows. This is especially useful for those working with multiple screens.

Works with:

  • Jupyter notebook
  • Jupyter lab
  • Voila (version<0.5 only when running standalone)
  • Solara (version>=1.22)

In the Jupyter notebook and Jupyter lab environments, ipypopout will use either Solara or Voila to create the popout window. The exist

Installation

To use the Solara backend

$ pip install "ipypopout[solara]"

To use the Voila backend

$ pip install "ipypopout[voila]"

Note: ipypopout is not compatible with Voila >= 0.5 standalone (e.g. running as voila mynotebook.ipynb). If you use Voila >=0.5 as a Jupyter server extension, such as when running Jupyter Lab, ipypopout can only use solara and therefore you need to pip install ipypopout[solara].

Usage

With ipywidgets

import ipywidgets as widgets
from ipypopout import PopoutButton

main = widgets.VBox()

# see https://developer.mozilla.org/en-US/docs/Web/API/Window/open#window_features
# for window_features
popout_button = PopoutButton(main, window_features='popup,width=400,height=600')

slider1 = widgets.IntSlider(value=1)
slider2 = widgets.IntSlider(value=2)
result = widgets.Label()
def update_result(_ignore=None):
    result.value = value=f"Sum of {slider1.value} and {slider2.value} = {slider1.value + slider2.value}"
update_result()

main.children = (slider1, slider2, result, popout_button)
slider1.observe(update_result, "value")
slider2.observe(update_result, "value")

display(main)
ipywidgets-demo-1k.mp4

With Solara

import solara
import plotly.express as px
import numpy as np
from ipypopout import PopoutButton


freq = solara.reactive(1)
damping = solara.reactive(0.5)

t = np.arange(0, 100, 0.1)/10

@solara.component
def Page():
    target_model_id = solara.use_reactive("")

    y = np.sin(t * 2 * np.pi * freq.value) * np.exp(-t*damping.value)

    with solara.Column():
        with solara.Card("Controls") as control:
            solara.SliderFloat("Freq", value=freq, min=1, max=10)
            solara.SliderFloat("zeta", value=damping, min=0, max=2)
            if target_model_id.value:
                PopoutButton.element(target_model_id=target_model_id.value, window_features='popup,width=400,height=300')
        fig = px.line(x=t, y=y)
        solara.FigurePlotly(fig)
    # with solara we have to use use_effect + get_widget to get the widget id
    solara.use_effect(lambda: target_model_id.set(solara.get_widget(control)._model_id))
display(Page())

Because Solara creates elements instead of widgets, we have to use the use_effect/get_widget trick to feed the widget ID to the PopoutButton.

solara-demo-notebook2.mp4

API

Which backend to use

Note that ipypopout will automatically detect if it can use Solara, and use it if available, otherwise it will use Voila. If you want to force the use of Voila, you can set the environment variable IPYPOPOUT_USE_BACKEND=voila, the other options are auto (the default) and solara (in case our auto detect fails).