GUI Handles¶
- class viser.CommandHandle[source]¶
Handle for a command registered in the command palette.
Commands are shown in a command palette (Ctrl/Cmd+K, also Ctrl/Cmd+Shift+P on non-Firefox browsers) and can optionally be triggered via hotkeys.
(Experimental) The command palette API may change in future releases.
- modifier: KeyModifier | None¶
Modifier-combo held with the hotkey, e.g.
"cmd/ctrl"or"cmd/ctrl+shift".Nonematches “no modifiers held”.
- on_trigger(func: Callable[[CommandEvent], NoneOrCoroutine]) Callable[[CommandEvent], NoneOrCoroutine][source]¶
Attach a function to call when this command is triggered.
Note: - If func is a regular function (defined with def), it will be executed in a thread pool. - If func is an async function (defined with async def), it will be executed in the event loop.
Using async functions can be useful for reducing race conditions.
- Parameters:
func (Callable[[CommandEvent], NoneOrCoroutine])
- Return type:
Callable[[CommandEvent], NoneOrCoroutine]
- class viser.GuiButtonGroupHandle[source]¶
Handle for a button group input in our visualizer.
- on_click(func: Callable[[GuiEvent[TGuiHandle]], NoneOrCoroutine]) Callable[[GuiEvent[TGuiHandle]], NoneOrCoroutine][source]¶
Attach a function to call when a button in the group is clicked.
Note: - If func is a regular function (defined with def), it will be executed in a thread pool. - If func is an async function (defined with async def), it will be executed in the event loop.
Using async functions can be useful for reducing race conditions.
- class viser.GuiButtonHandle[source]¶
Handle for a button input in our visualizer.
- value: bool¶
Value of the button. Set to True when the button is pressed. Can be manually set back to False.
- property icon: IconName | None¶
Icon to display on the button. When set to None, no icon is displayed.
- on_click(func: Callable[[GuiEvent[TGuiHandle]], NoneOrCoroutine]) Callable[[GuiEvent[TGuiHandle]], NoneOrCoroutine][source]¶
Attach a function to call when a button is pressed.
Note: - If func is a regular function (defined with def), it will be executed in a thread pool. - If func is an async function (defined with async def), it will be executed in the event loop.
Using async functions can be useful for reducing race conditions.
- on_hold(func: None = None, callback_hz: float = 10.0) Callable[[_HoldCallback], _HoldCallback][source]¶
- on_hold(func: _HoldCallback, callback_hz: float = 10.0) _HoldCallback
Attach a function to call repeatedly while a button is held down.
The callback will be triggered immediately when the button is pressed, and then repeatedly at the specified frequency until released.
- Can be used as a decorator with or without arguments:
@button.on_hold def callback(event): …
@button.on_hold(callback_hz=30.0) def callback(event): …
- Or called directly:
button.on_hold(callback) button.on_hold(callback, callback_hz=30.0)
- Parameters:
func – The callback function to attach. If None, returns a decorator.
callback_hz – The frequency in Hz at which to call the callback while the button is held. Defaults to 10.0 Hz.
Note: - If func is a regular function (defined with def), it will be executed in a thread pool. - If func is an async function (defined with async def), it will be executed in the event loop.
Using async functions can be useful for reducing race conditions.
- class viser.GuiCheckboxHandle[source]¶
Handle for checkbox inputs.
- on_update(func: Callable[[GuiEvent[TGuiHandle]], NoneOrCoroutine]) Callable[[GuiEvent[TGuiHandle]], NoneOrCoroutine]¶
Attach a function to call when a GUI input is updated.
Note: - If func is a regular function (defined with def), it will be executed in a thread pool. - If func is an async function (defined with async def), it will be executed in the event loop.
Using async functions can be useful for reducing race conditions.
- class viser.GuiDropdownHandle[source]¶
Handle for a dropdown-style GUI input in our visualizer.
- value: StringType¶
Value of the input. Represents the currently selected option in the dropdown.
- property options: tuple[StringType, ...]¶
Options for our dropdown. Synchronized automatically when assigned.
For projects that care about typing: the static type of options should be consistent with the StringType associated with a handle. Literal types will be inferred where possible when handles are instantiated; for the most flexibility, we can declare handles as GuiDropdownHandle[str].
- on_update(func: Callable[[GuiEvent[TGuiHandle]], NoneOrCoroutine]) Callable[[GuiEvent[TGuiHandle]], NoneOrCoroutine]¶
Attach a function to call when a GUI input is updated.
Note: - If func is a regular function (defined with def), it will be executed in a thread pool. - If func is an async function (defined with async def), it will be executed in the event loop.
Using async functions can be useful for reducing race conditions.
- class viser.GuiFolderHandle[source]¶
Use as a context to place GUI elements into a folder.
- remove() None[source]¶
Permanently remove this folder and all contained GUI elements from the visualizer.
- Return type:
None
- class viser.GuiFormHandle[source]¶
Use as a context to place GUI elements into a form.
A form is a folder whose children’s values can be committed together by calling
submit()(typically from a button’son_clickhandler) or by pressing Enter in a single-line text input inside the form.Children of a form behave exactly like children of a folder.
on_updatecallbacks on individual inputs continue to fire on every keystroke; the form’son_submit()callback fires only when the form is submitted. Register one or both depending on whether you want live or commit semantics.The form’s client-side dirty indicator highlights when any descendant input has been edited since the last submit.
Forms cannot be nested. Calling
GuiApi.add_form()inside an existing form’s context will raiseValueError, because nested<form>elements are invalid HTML on the client.Example:
with server.gui.add_form("Profile") as form: name = server.gui.add_text("Name", "") age = server.gui.add_number("Age", 0) save = server.gui.add_button("Save") save.on_click(lambda _: form.submit()) @form.on_submit def _(event): print(name.value, age.value)
- on_submit(func: Callable[[GuiEvent[GuiFormHandle]], NoneOrCoroutine]) Callable[[GuiEvent[GuiFormHandle]], NoneOrCoroutine][source]¶
Attach a function to call when the form is submitted.
on_submitis independent fromon_updatecallbacks on child inputs: childon_updatecallbacks fire on every keystroke (as normal), and the form’son_submitfires when commit happens (viaform.submit()or Enter in a single-line text input).Note: - If func is a regular function (defined with def), it will be executed in a thread pool. - If func is an async function (defined with async def), it will be executed in the event loop.
- Parameters:
func (Callable[[GuiEvent[GuiFormHandle]], NoneOrCoroutine])
- Return type:
Callable[[GuiEvent[GuiFormHandle]], NoneOrCoroutine]
- remove_submit_callback(callback: Literal['all'] | Callable = 'all') None[source]¶
Remove submit callbacks from the form.
- Parameters:
callback (Literal['all'] | ~typing.Callable) – Either “all” to remove all callbacks, or a specific callback function to remove.
- Return type:
None
- submit() None[source]¶
Programmatically submit this form.
Fires all registered
on_submitcallbacks and broadcasts aGuiFormSubmitMessageto all clients so their dirty indicators are cleared.- Return type:
None
- remove() None¶
Permanently remove this folder and all contained GUI elements from the visualizer.
- Return type:
None
- class viser.GuiImageHandle[source]¶
Handle for updating and removing images.
- property image: ndarray¶
Current content of this image element. Synchronized automatically when assigned.
- class viser.GuiInputHandle[source]¶
A handle is created for each GUI element that is added in viser. Handles can be used to read and write state.
When a GUI element is added via
ViserServer.gui, state is synchronized between all connected clients. When a GUI element is added viaClientHandle.gui, state is local to a specific client.- on_update(func: Callable[[GuiEvent[TGuiHandle]], NoneOrCoroutine]) Callable[[GuiEvent[TGuiHandle]], NoneOrCoroutine][source]¶
Attach a function to call when a GUI input is updated.
Note: - If func is a regular function (defined with def), it will be executed in a thread pool. - If func is an async function (defined with async def), it will be executed in the event loop.
Using async functions can be useful for reducing race conditions.
- class viser.GuiMarkdownHandle[source]¶
Handling for updating and removing markdown elements.
- class viser.GuiMultiSliderHandle[source]¶
Handle for multi-slider inputs.
- on_update(func: Callable[[GuiEvent[TGuiHandle]], NoneOrCoroutine]) Callable[[GuiEvent[TGuiHandle]], NoneOrCoroutine]¶
Attach a function to call when a GUI input is updated.
Note: - If func is a regular function (defined with def), it will be executed in a thread pool. - If func is an async function (defined with async def), it will be executed in the event loop.
Using async functions can be useful for reducing race conditions.
- class viser.GuiNumberHandle[source]¶
Handle for number inputs.
- value: IntOrFloat¶
Value of the input. Synchronized automatically when assigned.
- on_update(func: Callable[[GuiEvent[TGuiHandle]], NoneOrCoroutine]) Callable[[GuiEvent[TGuiHandle]], NoneOrCoroutine]¶
Attach a function to call when a GUI input is updated.
Note: - If func is a regular function (defined with def), it will be executed in a thread pool. - If func is an async function (defined with async def), it will be executed in the event loop.
Using async functions can be useful for reducing race conditions.
- class viser.GuiPlotlyHandle[source]¶
Handle for updating and removing Plotly figures.
- property figure: go.Figure¶
Current Plotly figure. Synchronized automatically when assigned.
- class viser.GuiRgbHandle[source]¶
Handle for RGB color inputs.
- on_update(func: Callable[[GuiEvent[TGuiHandle]], NoneOrCoroutine]) Callable[[GuiEvent[TGuiHandle]], NoneOrCoroutine]¶
Attach a function to call when a GUI input is updated.
Note: - If func is a regular function (defined with def), it will be executed in a thread pool. - If func is an async function (defined with async def), it will be executed in the event loop.
Using async functions can be useful for reducing race conditions.
- class viser.GuiRgbaHandle[source]¶
Handle for RGBA color inputs.
- on_update(func: Callable[[GuiEvent[TGuiHandle]], NoneOrCoroutine]) Callable[[GuiEvent[TGuiHandle]], NoneOrCoroutine]¶
Attach a function to call when a GUI input is updated.
Note: - If func is a regular function (defined with def), it will be executed in a thread pool. - If func is an async function (defined with async def), it will be executed in the event loop.
Using async functions can be useful for reducing race conditions.
- class viser.GuiSliderHandle[source]¶
Handle for slider inputs.
- value: IntOrFloat¶
Value of the input. Synchronized automatically when assigned.
- on_update(func: Callable[[GuiEvent[TGuiHandle]], NoneOrCoroutine]) Callable[[GuiEvent[TGuiHandle]], NoneOrCoroutine]¶
Attach a function to call when a GUI input is updated.
Note: - If func is a regular function (defined with def), it will be executed in a thread pool. - If func is an async function (defined with async def), it will be executed in the event loop.
Using async functions can be useful for reducing race conditions.
- class viser.GuiTabGroupHandle[source]¶
Handle for a tab group. Call
add_tab()to add a tab.- add_tab(label: str, icon: IconName | None = None) GuiTabHandle¶
Add a tab. Returns a handle we can use to add GUI elements to it.
- Parameters:
label (str)
icon (IconName | None)
- Return type:
- class viser.GuiTextHandle[source]¶
Handle for text inputs.
- on_update(func: Callable[[GuiEvent[TGuiHandle]], NoneOrCoroutine]) Callable[[GuiEvent[TGuiHandle]], NoneOrCoroutine]¶
Attach a function to call when a GUI input is updated.
Note: - If func is a regular function (defined with def), it will be executed in a thread pool. - If func is an async function (defined with async def), it will be executed in the event loop.
Using async functions can be useful for reducing race conditions.
- class viser.GuiUploadButtonHandle[source]¶
Handle for an upload file button in our visualizer.
The .value attribute will be updated with the contents of uploaded files.
- value: UploadedFile¶
Value of the input. Contains information about the uploaded file.
- property icon: IconName | None¶
Icon to display on the upload button. When set to None, no icon is displayed.
- on_upload(func: Callable[[GuiEvent[TGuiHandle]], NoneOrCoroutine]) Callable[[GuiEvent[TGuiHandle]], NoneOrCoroutine][source]¶
Attach a function to call when a file is uploaded.
Note: - If func is a regular function (defined with def), it will be executed in a thread pool. - If func is an async function (defined with async def), it will be executed in the event loop.
Using async functions can be useful for reducing race conditions.
- class viser.GuiUplotHandle[source]¶
Handle for updating and removing Uplot figures.
- data: Tuple[npt.NDArray[np.float64], ...]¶
Tuple of 1D numpy arrays containing chart data. First array is x-axis data, subsequent arrays are y-axis data for each series. All arrays must have matching lengths. Minimum 2 arrays required.
- mode: Literal[1, 2] | None¶
1 = aligned (all series share axes), 2 = faceted (each series gets its own subplot panel). Defaults to 1.
- Type:
Chart layout mode
- series: Tuple[uplot.Series, ...]¶
Series configuration objects defining visual appearance (colors, line styles, labels) and behavior for each data array. Must match data tuple length.
- bands: Tuple[uplot.Band, ...] | None¶
High/low range visualizations between adjacent series indices. Useful for confidence intervals, error bounds, or min/max ranges.
- scales: Dict[str, uplot.Scale] | None¶
Scale definitions controlling data-to-pixel mapping and axis ranges. Enables features like auto-ranging, manual bounds, time-based scaling, and logarithmic distributions. Multiple scales support dual-axis charts.
- axes: Tuple[uplot.Axis, ...] | None¶
Axis configuration for positioning (top/right/bottom/left), tick formatting, grid styling, and spacing. Controls visual appearance of chart axes.
- legend: uplot.Legend | None¶
Legend display options including positioning, styling, and custom value formatting for hover states.
- cursor: uplot.Cursor | None¶
Interactive cursor behavior including hover detection, drag-to-zoom, and crosshair appearance. Controls user interaction with the chart.
- focus: uplot.Focus | None¶
Visual highlighting when hovering over series. Controls alpha transparency of non-focused series to emphasize the active one.
- class viser.GuiVector2Handle[source]¶
Handle for 2D vector inputs.
- on_update(func: Callable[[GuiEvent[TGuiHandle]], NoneOrCoroutine]) Callable[[GuiEvent[TGuiHandle]], NoneOrCoroutine]¶
Attach a function to call when a GUI input is updated.
Note: - If func is a regular function (defined with def), it will be executed in a thread pool. - If func is an async function (defined with async def), it will be executed in the event loop.
Using async functions can be useful for reducing race conditions.
- class viser.GuiVector3Handle[source]¶
Handle for 3D vector inputs.
- on_update(func: Callable[[GuiEvent[TGuiHandle]], NoneOrCoroutine]) Callable[[GuiEvent[TGuiHandle]], NoneOrCoroutine]¶
Attach a function to call when a GUI input is updated.
Note: - If func is a regular function (defined with def), it will be executed in a thread pool. - If func is an async function (defined with async def), it will be executed in the event loop.
Using async functions can be useful for reducing race conditions.
- class viser.MainPanelHandle[source]¶
Handle for the main control panel. Returned by
GuiApi.main_panel.Supports the same placement / sizing / minimize commands as
PanelHandle, but nothing else from it: the main panel has no tabs (its content is the inline GUI tree), novisibleproperty, and cannot be removed. Because the control panel renders on every client, it is a legal anchor for other panels’dock_*commands from any scope.A fresh handle is returned on each access; placement state is keyed off the control panel’s fixed uuid, so handles are interchangeable.
Note
Panels are a new API surface; method names and placement semantics may still evolve in upcoming releases.
- dock_above(anchor: PanelHandle | MainPanelHandle) None¶
Stack this panel directly above another panel (a column split).
The
anchormust itself be DOCKED (a column split needs a docked neighbor to split against). If the anchor is floating or not yet placed, this falls back to docking on the right edge (with a warning); dock the anchor first.- Parameters:
anchor (PanelHandle | MainPanelHandle)
- Return type:
None
- dock_below(anchor: PanelHandle | MainPanelHandle) None¶
Stack this panel directly below another panel (a column split).
The
anchormust itself be DOCKED (a column split needs a docked neighbor to split against). If the anchor is floating or not yet placed, this falls back to docking on the right edge (with a warning); dock the anchor first.- Parameters:
anchor (PanelHandle | MainPanelHandle)
- Return type:
None
- dock_left() None¶
Dock this panel to the left viewport edge.
Each new left-dock is inserted at the innermost position, so several panels docked to the left appear in call order from the edge inward. Calling again repositions an already-placed panel.
- Return type:
None
- dock_right() None¶
Dock this panel to the right viewport edge.
Each new right-dock is inserted at the innermost position, so several panels docked to the right appear in call order from the edge inward. Calling again repositions an already-placed panel.
- Return type:
None
- expand() None¶
Expand (un-minimize) the panel, the inverse of
minimize().Like
minimize()this acts at container scope – expanding a panel reveals its whole stack (and clears a docked column’s rail) – and is imperative: it always expands, even if the user minimized the panel in the browser. Replayed to clients that connect later.- Return type:
None
- float(*, x: float | None = None, y: float | None = None, width: float | None = None, height: float | None = None) None¶
Float this panel at an explicit position and size, in CSS pixels.
x/yare measured relative to the viewport – the canvas area inside any docked panels:A non-negative value is a gap from the left / top:
float(x=40)lands 40px from the canvas left edge (clear of a left-docked panel, not under it).A negative value is a gap from the right / bottom:
float(x=-15)puts the panel’s right edge 15px from the canvas right edge. Sofloat(x=-15, y=15)is the top-right corner, andfloat(x=-15, y=-15)the bottom-right.
The panel re-resolves against these edges as the canvas changes (a dock added/removed, the window resized), so an edge-anchored panel stays put. Any argument left as
Noneuses a client-chosen default (top-left);width/heightset the floating window size.
- minimize() None¶
Minimize the panel (collapse it to a bar / rail strip).
Collapse is applied to the panel’s container – its floating window or its docked column – so panels stacked together minimize together, exactly like the on-screen minimize control. Imperative, like the
dock_*/float()commands: it always minimizes, even if the user expanded the panel in the browser. Replayed to clients that connect later. On the mobile bottom sheet (where panels render as sections, not windows) this collapses the panel’s section.TODO: add a matching imperative collapse/expand method for folders (
GuiApi.add_folder()), which today only has theexpand_by_defaultcreation kwarg.- Return type:
None
- set_height(height: float) None¶
Set the panel height in pixels.
Applies only to floating panels (sets the window height). A docked panel – whether solo or stacked via
dock_above()/dock_below()– sizes to its split weights, soset_heighthas no effect there.- Parameters:
height (float)
- Return type:
None
- class viser.PanelHandle[source]¶
Handle for a standalone panel: a dockable / floating GUI container that lives outside the main control panel.
Create with
GuiApi.add_panel(). Add content withadd_tab(), and place it with the imperativedock_*/float()commands. A panel is a dedicated top-level entity (like a modal) – it is NOT part of the inline GUI tree – that carries its own tabs; a single-tab panel renders as a plain header.Placement, sizing, and collapse are imperative commands, not synced state: they apply to connected clients and replay to clients that connect later, but the current layout is never read back from clients. There are no readable
.width/ position / minimized properties, and a user dragging or minimizing the panel afterward wins until the next explicit command. (This is why sizing isset_width()rather than a.widthproperty.)minimize()/expand()act on the panel’s container – its floating window or its docked column – so panels stacked together minimize together, exactly like the on-screen minimize control.The server owns a panel’s existence: users can rearrange, drag, minimize, and resize a panel, but cannot close it from the UI. A panel disappears only when
remove()is called.Note
Panels are a new API surface; method names and placement semantics may still evolve in upcoming releases.
- add_tab(label: str, icon: IconName | None = None) GuiTabHandle[source]¶
Add a tab to the panel, returning a handle to populate it as a context.
A single-tab panel renders as a plain header; multiple tabs render as a tab strip. Raises if the panel has been removed (the shared
_TabContainerMixinguard).- Parameters:
label (str)
icon (IconName | None)
- Return type:
- remove() None[source]¶
Permanently remove this panel and all its tabs / contained elements.
This is the only way a panel disappears – there is no UI close button (see
PanelHandle).- Return type:
None
- dock_above(anchor: PanelHandle | MainPanelHandle) None¶
Stack this panel directly above another panel (a column split).
The
anchormust itself be DOCKED (a column split needs a docked neighbor to split against). If the anchor is floating or not yet placed, this falls back to docking on the right edge (with a warning); dock the anchor first.- Parameters:
anchor (PanelHandle | MainPanelHandle)
- Return type:
None
- dock_below(anchor: PanelHandle | MainPanelHandle) None¶
Stack this panel directly below another panel (a column split).
The
anchormust itself be DOCKED (a column split needs a docked neighbor to split against). If the anchor is floating or not yet placed, this falls back to docking on the right edge (with a warning); dock the anchor first.- Parameters:
anchor (PanelHandle | MainPanelHandle)
- Return type:
None
- dock_left() None¶
Dock this panel to the left viewport edge.
Each new left-dock is inserted at the innermost position, so several panels docked to the left appear in call order from the edge inward. Calling again repositions an already-placed panel.
- Return type:
None
- dock_right() None¶
Dock this panel to the right viewport edge.
Each new right-dock is inserted at the innermost position, so several panels docked to the right appear in call order from the edge inward. Calling again repositions an already-placed panel.
- Return type:
None
- expand() None¶
Expand (un-minimize) the panel, the inverse of
minimize().Like
minimize()this acts at container scope – expanding a panel reveals its whole stack (and clears a docked column’s rail) – and is imperative: it always expands, even if the user minimized the panel in the browser. Replayed to clients that connect later.- Return type:
None
- float(*, x: float | None = None, y: float | None = None, width: float | None = None, height: float | None = None) None¶
Float this panel at an explicit position and size, in CSS pixels.
x/yare measured relative to the viewport – the canvas area inside any docked panels:A non-negative value is a gap from the left / top:
float(x=40)lands 40px from the canvas left edge (clear of a left-docked panel, not under it).A negative value is a gap from the right / bottom:
float(x=-15)puts the panel’s right edge 15px from the canvas right edge. Sofloat(x=-15, y=15)is the top-right corner, andfloat(x=-15, y=-15)the bottom-right.
The panel re-resolves against these edges as the canvas changes (a dock added/removed, the window resized), so an edge-anchored panel stays put. Any argument left as
Noneuses a client-chosen default (top-left);width/heightset the floating window size.
- minimize() None¶
Minimize the panel (collapse it to a bar / rail strip).
Collapse is applied to the panel’s container – its floating window or its docked column – so panels stacked together minimize together, exactly like the on-screen minimize control. Imperative, like the
dock_*/float()commands: it always minimizes, even if the user expanded the panel in the browser. Replayed to clients that connect later. On the mobile bottom sheet (where panels render as sections, not windows) this collapses the panel’s section.TODO: add a matching imperative collapse/expand method for folders (
GuiApi.add_folder()), which today only has theexpand_by_defaultcreation kwarg.- Return type:
None
- set_height(height: float) None¶
Set the panel height in pixels.
Applies only to floating panels (sets the window height). A docked panel – whether solo or stacked via
dock_above()/dock_below()– sizes to its split weights, soset_heighthas no effect there.- Parameters:
height (float)
- Return type:
None
- viser.PlaceableHandle = 'PanelHandle | MainPanelHandle'¶
str(object=’’) -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to ‘strict’.