panel-holoviews skill update#140
Conversation
|
FYI @ahuang11 |
There was a problem hiding this comment.
Pull request overview
Updates the documentation “skills” content to consolidate and expand guidance for integrating HoloViews/hvPlot into Panel apps, following up on the earlier interactions-focused skill.
Changes:
- Adds a new
panel-holoviewsskill with expanded best-practice patterns (DynamicMap, streams, linked selections, sizing, jslink). - Updates the
panelskill to reference the newpanel-holoviewsskill guidance. - Removes the older
panel-holoviews-interactionsskill and updatesget_skilldocstring examples accordingly.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
src/holoviz_mcp/holoviz_mcp/server.py |
Updates get_skill docstring examples to include panel-holoviews. |
src/holoviz_mcp/config/resources/skills/panel.md |
Adjusts plotting guidance to point readers to relevant skills. |
src/holoviz_mcp/config/resources/skills/panel-holoviews.md |
Introduces the consolidated Panel+HoloViews skill content. |
src/holoviz_mcp/config/resources/skills/panel-holoviews-interactions.md |
Deletes the prior interactions-focused skill document. |
| | Cross-filtering | `hv.link_selections.instance()` | Building manual stream wiring | | ||
| | Streaming data | `Pipe` (replace) or `Buffer` (append) streams | Replacing pane.object in a loop | | ||
| | Renderer theme | `pn.pane.HoloViews(plot, theme=...)` | `hv.renderer('bokeh').theme = ...` | | ||
| | Client-side styling | `widget.jslink(plot, value='glyph.fill_alpha')` | DynamicMap for pure visual tweaks | |
There was a problem hiding this comment.
The summary checklist repeats the same jslink pattern (widget.jslink(plot, ...)) that’s likely incorrect for HoloViews objects (see earlier jslink section). Updating this row to reference linking to a Pane/rendered model will keep the checklist consistent with working code.
| | Client-side styling | `widget.jslink(plot, value='glyph.fill_alpha')` | DynamicMap for pure visual tweaks | | |
| | Client-side styling | `widget.jslink(pane, value='object.glyph.fill_alpha')` | DynamicMap for pure visual tweaks | |
| name (str): The name of the skill to get. For example, "panel", "panel-material-ui", | ||
| "panel-holoviews", "panel-custom-components" etc. |
There was a problem hiding this comment.
The docstring’s parameter description wraps onto a new line without indentation, which renders awkwardly in generated docs. Consider indenting the continuation line so it aligns with the start of the description text (or reformat as a single line / bullet list).
| name (str): The name of the skill to get. For example, "panel", "panel-material-ui", | |
| "panel-holoviews", "panel-custom-components" etc. | |
| name (str): The name of the skill to get, for example "panel", "panel-material-ui", "panel-holoviews", "panel-custom-components", etc. |
| - DON'T set `hv.renderer('bokeh').theme = 'dark_minimal'` | ||
|
|
||
| DO follow the hvplot and holoviews best practice guides! | ||
| DO follow the relevant `hvplot`, `holoviews` and `panel-holoviews` skills/ best practice guides! |
There was a problem hiding this comment.
This line breaks the surrounding bullet-list style (missing leading "- ") and has awkward wording/spacing ("skills/ best"). Consider keeping it as a bullet and rephrasing to remove the stray slash/space so the guidance reads cleanly.
| DO follow the relevant `hvplot`, `holoviews` and `panel-holoviews` skills/ best practice guides! | |
| - DO follow the relevant `hvplot`, `holoviews`, and `panel-holoviews` skills and best-practice guides! |
| # Float slider → glyph fill alpha (also works for size, line_width, fill_color, etc.) | ||
| widget = pn.widgets.FloatSlider(value=1, step=0.01) | ||
| plot = hv.Points((x, y)).opts(size=10) | ||
| widget.jslink(plot, value='glyph.fill_alpha') | ||
|
|
||
| # Text input → plot title | ||
| widget = pn.widgets.TextInput(value="Title") | ||
| plot = hv.Curve((x, y)).opts(title="Title") | ||
| widget.jslink(plot, value="plot.title.text") | ||
|
|
||
| # Text input → axis label | ||
| widget = pn.widgets.TextInput(value="X Label") | ||
| plot = hv.Curve((x, y)).opts(xlabel="X Label") | ||
| widget.jslink(plot, value="xaxis.axis_label") | ||
|
|
||
| # RadioButtonGroup → title alignment | ||
| widget = pn.widgets.RadioButtonGroup(options=["left", "center", "right"]) | ||
| widget.jslink(plot, value="plot.title.align") |
There was a problem hiding this comment.
The jslink examples are linking widgets directly to a HoloViews object (e.g., widget.jslink(plot, ...)). jslink expects a Panel/Bokeh model target; a bare HoloViews element typically isn’t linkable until it’s wrapped/rendered (e.g., via a pn.pane.HoloViews pane). As written, these snippets are likely to fail for readers.
| # Float slider → glyph fill alpha (also works for size, line_width, fill_color, etc.) | |
| widget = pn.widgets.FloatSlider(value=1, step=0.01) | |
| plot = hv.Points((x, y)).opts(size=10) | |
| widget.jslink(plot, value='glyph.fill_alpha') | |
| # Text input → plot title | |
| widget = pn.widgets.TextInput(value="Title") | |
| plot = hv.Curve((x, y)).opts(title="Title") | |
| widget.jslink(plot, value="plot.title.text") | |
| # Text input → axis label | |
| widget = pn.widgets.TextInput(value="X Label") | |
| plot = hv.Curve((x, y)).opts(xlabel="X Label") | |
| widget.jslink(plot, value="xaxis.axis_label") | |
| # RadioButtonGroup → title alignment | |
| widget = pn.widgets.RadioButtonGroup(options=["left", "center", "right"]) | |
| widget.jslink(plot, value="plot.title.align") | |
| import panel as pn | |
| import holoviews as hv | |
| hv.extension("bokeh") | |
| # Float slider → glyph fill alpha (also works for size, line_width, fill_color, etc.) | |
| widget = pn.widgets.FloatSlider(value=1, step=0.01) | |
| plot = hv.Points((x, y)).opts(size=10) | |
| pane = pn.pane.HoloViews(plot) | |
| widget.jslink(pane, value='glyph.fill_alpha') | |
| # Text input → plot title | |
| widget = pn.widgets.TextInput(value="Title") | |
| plot = hv.Curve((x, y)).opts(title="Title") | |
| pane = pn.pane.HoloViews(plot) | |
| widget.jslink(pane, value="plot.title.text") | |
| # Text input → axis label | |
| widget = pn.widgets.TextInput(value="X Label") | |
| plot = hv.Curve((x, y)).opts(xlabel="X Label") | |
| pane = pn.pane.HoloViews(plot) | |
| widget.jslink(pane, value="xaxis.axis_label") | |
| # RadioButtonGroup → title alignment | |
| widget = pn.widgets.RadioButtonGroup(options=["left", "center", "right"]) | |
| plot = hv.Curve((x, y)) | |
| pane = pn.pane.HoloViews(plot) | |
| widget.jslink(pane, value="plot.title.align") |
| plot = hv.Curve((x, y)) | ||
| widget.jslink(plot, code={'value': """ |
There was a problem hiding this comment.
Similarly, this example links to a HoloViews element and then references Bokeh model names in the JS callback. Unless the target is a rendered/pane object that exposes those Bokeh models, the callback won’t have x_range available and the link will not work. Consider demonstrating jslink against a pn.pane.HoloViews (or explicit Bokeh model) target instead.
| plot = hv.Curve((x, y)) | |
| widget.jslink(plot, code={'value': """ | |
| curve = hv.Curve((x, y)) | |
| plot = pn.pane.HoloViews(curve) | |
| widget.jslink(plot, code={'value': """ | |
| const x_range = target.x_range; |
Follow up to #139.
I did some rounds asking Claude to plan an update to the panel-holoviews skill guided by https://github.com/anthropics/skills/blob/main/skills/skill-creator/SKILL.md. Then asked it to pytest all the guidence and example code. Then asked it to create a folder of example apps I could test. We iterated a couple of times to improve the guidance.