Skip to content

Update custom components#171

Open
ahuang11 wants to merge 2 commits intoMarcSkovMadsen:mainfrom
ahuang11:patch-2
Open

Update custom components#171
ahuang11 wants to merge 2 commits intoMarcSkovMadsen:mainfrom
ahuang11:patch-2

Conversation

@ahuang11
Copy link
Copy Markdown
Contributor

@ahuang11 ahuang11 commented Apr 7, 2026

Separate out testing from developing custom components. Also, improve custom components repo selection.

@ahuang11 ahuang11 requested a review from MarcSkovMadsen as a code owner April 7, 2026 00:15
Copilot AI review requested due to automatic review settings April 7, 2026 00:15
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates the panel-custom-components skill documentation to better guide users building custom Panel components, with added guidance around CDN/import-map choices and JS↔Python communication patterns.

Changes:

  • Added a CDN selection guide and expanded guidance for plugin-based JS libraries (e.g., FullCalendar-style ecosystems).
  • Clarified JS↔Python communication patterns and emphasized correct usage of _send_msg vs nonexistent send_msg.
  • Slimmed down the Playwright testing section in favor of referencing a dedicated Playwright skill; bumped skill version to 1.1.0.

---
name: panel-custom-components
description: Build custom Panel components using JSComponent (vanilla JS, web components), ReactComponent (React/JSX), AnyWidgetComponent (AnyWidget spec for cross-platform), or MaterialUIComponent (Material UI themed). Use when wrapping JS libraries, creating interactive widgets, or building themed components. Includes decision guide, best practices, DOs/DON'Ts, and Playwright UI testing patterns.
description: Build custom Panel components using JSComponent (vanilla JS, web components), ReactComponent (React/JSX), AnyWidgetComponent (AnyWidget spec for cross-platform), or MaterialUIComponent (Material UI themed). Use when wrapping JS libraries, creating interactive widgets, or building themed components. Includes decision guide, CDN selection guide, best practices, and DOs/DON'Ts. For Playwright UI testing patterns, see the `panel-pytest-playwright` skill.
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

panel-pytest-playwright is referenced as an existing skill, but there is no corresponding skills/panel-pytest-playwright/ in this repo. Either add that skill (so cross-references resolve) or change these references to an existing skill/path.

Suggested change
description: Build custom Panel components using JSComponent (vanilla JS, web components), ReactComponent (React/JSX), AnyWidgetComponent (AnyWidget spec for cross-platform), or MaterialUIComponent (Material UI themed). Use when wrapping JS libraries, creating interactive widgets, or building themed components. Includes decision guide, CDN selection guide, best practices, and DOs/DON'Ts. For Playwright UI testing patterns, see the `panel-pytest-playwright` skill.
description: Build custom Panel components using JSComponent (vanilla JS, web components), ReactComponent (React/JSX), AnyWidgetComponent (AnyWidget spec for cross-platform), or MaterialUIComponent (Material UI themed). Use when wrapping JS libraries, creating interactive widgets, or building themed components. Includes decision guide, CDN selection guide, best practices, and DOs/DON'Ts. For Playwright UI testing patterns, refer to the project's Playwright testing documentation and existing testing skills.

Copilot uses AI. Check for mistakes.
Comment on lines +359 to +365
# In Python -- _handle_msg receives the dict from JS
import json

class MyCalendar(JSComponent):
current_date = param.String(default="")
current_view = param.String(default="")
clicked_event = param.Dict(default={})
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Python example for _handle_msg uses param.String / param.Dict but the snippet only imports json. Add import param (or make the snippet explicitly rely on an earlier import) so it’s copy/paste runnable.

Copilot uses AI. Check for mistakes.
});
},
eventClick(info) {
model.send_msg({ clicked_event: JSON.stringify(serializeEvent(info.event)) });
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This snippet calls serializeEvent(info.event) but serializeEvent is not defined anywhere else in the document. Define it (even minimally) or replace with an explicit field extraction so readers can run the example without hitting a ReferenceError.

Suggested change
model.send_msg({ clicked_event: JSON.stringify(serializeEvent(info.event)) });
model.send_msg({
clicked_event: JSON.stringify({
id: info.event.id,
title: info.event.title,
start: info.event.start ? info.event.start.toISOString() : null,
end: info.event.end ? info.event.end.toISOString() : null,
allDay: info.event.allDay,
})
});

Copilot uses AI. Check for mistakes.
Comment on lines +641 to +647
function loadPluginIfNeeded(viewName, pluginName) {
const toolbar = model.header_toolbar || {};
const inToolbar = Object.values(toolbar).some(v => v.includes(viewName));
if (model.initial_view.startsWith(viewName) || inToolbar) {
return import(`@fullcalendar/${pluginName}`).then(m => m.default);
}
return Promise.resolve(null);
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The plugin-loading example uses bare specifiers in dynamic imports (e.g. import(@fullcalendar/${pluginName}) and import("@fullcalendar/interaction")). In a browser this will fail unless the Python _importmap includes mappings for every plugin you might import (or a namespace mapping like "@fullcalendar/": "https://.../"). Consider adding the required _importmap snippet alongside this example.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants