Wunderbaum tree — minimal (standalone)¶
Source: examples/panels/wunderbaum/wunderbaum_panel_min.py
Test: tests/panels/wunderbaum/examples/test_wunderbaum_panel_min.py
The smallest possible Wunderbaum usage — a nested tree served on its own, no Panelini shell.
The code¶
import panel as pn
from panelini.panels.wunderbaum import Wunderbaum
pn.extension()
source = [
{
"title": "Node 1",
"key": "1",
"expanded": True,
"children": [
{"title": "Node 1.1", "key": "1.1"},
{
"title": "Node 1.2",
"key": "1.2",
"children": [
{"title": "Node 1.2.1", "key": "1.2.1"},
],
},
],
},
{"title": "Node 2", "key": "2"},
{"title": "Node 3", "key": "3"},
]
tree = Wunderbaum(source=source)
if __name__ == "__main__":
pn.serve(tree)
Wunderbaum is a standalone AnyWidgetComponent panel. Each node is a dict with a title, a unique key, optional children, and an optional expanded flag — that’s the entire contract for a read-only tree. Because it has no Panelini dependency, you can pn.serve(tree) directly.
What’s under the hood¶
graph LR
py[Python prop<br/>source] <--> bridge[AnyWidget bridge]
bridge <--> vue[Vue wrapper]
vue --> wb[wunderbaum JS]
wb --> dom[Shadow DOM rows]
sourceis aparamlist — reassign it and the frontend re-renders.The tree renders inside a shadow DOM; tests reach it via a small
findInShadowRootshelper.
How the test exercises it¶
The Playwright test imports source and tree from the module, serves it on a random port, and asserts that tree.source still has three roots, the .wunderbaum-wrapper is visible, and at least one .wb-row rendered.
See also¶
Wunderbaum tree inside panelini — the same tree inside a Panelini shell
Wunderbaum treegrid — columns — add columns for tree + table mode