panel icon indicating copy to clipboard operation
panel copied to clipboard

Define migration plan for integrating panel-material-ui into core Panel

Open philippjfr opened this issue 3 weeks ago • 16 comments

Overview

As Panel continues to evolve its UI and widget ecosystem, we want to define a clear, intentional migration path toward integrating the work in panel-material-ui into core Panel.

The Material UI widgets provide a more modern look and feel, improved consistency, and a cleaner API in several areas, but they are not 100% API-compatible with existing panel.widgets. Rather than forcing a sudden or breaking transition, we should introduce a structured, opt-in path that allows us to:

  • Incrementally adopt the new widgets
  • Preserve backwards compatibility
  • Resolve any remaining API inconsistencies
  • Align visual and behavioral aspects across the ecosystem

This issue proposes a staged migration plan centered around introducing a new panel.v2 namespace (with panel.ui noted as a possible alternative).

Goals

  • Provide a clear, low-risk migration path
  • Encourage adoption of modern widgets
  • Improve long-term API coherence and visual consistency
  • Give contributors and users a stable target for “future Panel” development

Proposed approach

1. Update examples and documentation

  • Update existing examples to use panel-material-ui widgets
  • Over time:
    • Make panel.v2 the default in “Getting Started” and primary docs
    • Clearly label panel.widgets examples as legacy

2. Introduce labelname compatibility

To reduce friction and support shared mental models:

  • Alias label and name for widgets where applicable

  • Ensure both work consistently across:

    • Core Panel widgets
    • panel-material-ui widgets
    • panel.v2 API
  • Standardize on label in new APIs and documentation

3. Introduce a panel.v2 namespace (opt-in)

Create a new namespace that exposes the next-generation widget API backed by Material UI components:

import panel.v2 as pn2

pn2.Select(label="Fruit", options=["Apple", "Banana"])

Key properties:

  • panel.v2 is explicitly opt-in
  • No breaking changes to panel.widgets
  • Documentation and examples can gradually move to panel.v2
  • Allows API cleanup and alignment without destabilizing existing apps

Alternative: panel.ui A panel.ui namespace could serve a similar purpose and may age better long-term than a versioned namespace. This remains an open design decision to be resolved during implementation.

4. Address API inconsistencies incrementally

Use panel.v2 as the place to clean up long-standing inconsistencies such as:

  • Parameter naming (name vs label, etc.)
  • Event semantics and update timing
  • Validation and error display
  • Defaults for sizing, spacing, and layout behavior

Some issues may be shimmed in legacy widgets; others may be resolved only in panel.v2.

5. Align some UI differences

Ensure consistent .loading behavior across core Panel and MUI components:

  • Unified busy / loading indicators
  • Avoid visible discrepancies when mixing legacy and panel.v2 components in the same app

Open questions

  • panel.v2 vs panel.ui: which namespace should we commit to?
  • How aggressively should we deprecate legacy widgets once panel.v2 stabilizes?

philippjfr avatar Dec 03 '25 09:12 philippjfr

pn2.Select(label="Fruit", options=["Apple", "Banana"])

Isn't this pn2.widgets.Select(...)?

maximlt avatar Dec 03 '25 09:12 maximlt

Yes, thanks. Though in panel-material-ui I do export all components into the global namespace. I wouldn't want to do that in Panel but I suppose it could be considered if we introduced pn.ui instead of pn.v2 and exported all components under that.

philippjfr avatar Dec 03 '25 09:12 philippjfr

Hello,

As it is openned as a discussion i have a question.

Instead of using another namespace, would it work to have some pn.extension("pmui") (or any similar command): if called, panel starts mapping objects from pn to pmui objects. Having called it, the user knows he entered WIP areas and is responsible on maintaining his code to API changes. But once it is over, only this like would have to be removed, and not do the job twice upgrade and clean up.

If not possible, pn.ui feels better to me.

For the deprecation question, are you planning to deprecate objects one by one when ready or all at once, in which case, i feel you can be aggressive if you state clearly in the error message what version use to keep user scripts working. Kind of like numpy 2, everyone knew, so we took care to install what worked.

tmoulignier avatar Dec 03 '25 09:12 tmoulignier

Instead of using another namespace, would it work to have some pn.extension("pmui")

Yes, that could work, though I might want a nicer spelling than pn.extension("pmui"), e.g. maybe pn.extension(ui='material') and then later pn.extension(ui='legacy'). Internally we'd just implement __new__ on the component and switch the component depending on the setting and you could locally override it by providing ui as a keyword in the constructor.

In terms of deprecation I think we'd keep the old widgets for a little while and allow the user to enable legacy mode or explicitly request them. But I don't know if there's an obvious way to "error", since we're not removing anything and but simply replacing it.

philippjfr avatar Dec 03 '25 10:12 philippjfr

I don't think pn.extension("pmui") would be understood by type checkers and language servers similarly to how they don't understand import hvplot.pandas adds .hvplot to a DataFrame. If that is the case I'm not in favor of the idea. It would make it even harder to understand api differences when switching between the legacy and pmui widgets.

MarcSkovMadsen avatar Dec 03 '25 16:12 MarcSkovMadsen

I think that's accurate, it would be nice if type checkers could do something like this could work:

class Widget:
    @overload
    def __new__(cls, *args, ui: Literal["material"], **params) -> MuiWidget: ...
    
    @overload
    def __new__(cls, *args, ui: Literal["legacy"], **params) -> Widget: ...

but alas I don't think there's any support for this kind of thing.

philippjfr avatar Dec 03 '25 16:12 philippjfr

Indeed i didn't find anything that would help going through this, so better drop it

tmoulignier avatar Dec 04 '25 07:12 tmoulignier

2. Introduce label ↔ name compatibility

Not too big of a fan for this. My gut says there should only be one way to do things as to not confuse new users on historical differences.

And to build on that point and agreeing with Marc "it even harder to understand api differences", I think it should be clear to new users the one way to do things and not mix and match them, so I propose a huge major release instead, while in the meantime, providing FutureWarnings on pn.extension() to pin panel<2 for current users (with the option of disabling the warning through a env var PANEL_LEGACY = 1 or setting pn.extension("legacy")), or ask them to install beta releases, or the actual panel-material-ui to test since it can already be mixed and matched with the legacy panel.

If not, I like pn.ui.Select and pn.mui.Select, but wondering whether it should all be under the same namespace, because pn.widgets.ChatInterface was migrated to pn.chat.ChatInterface in the end.

ahuang11 avatar Dec 04 '25 19:12 ahuang11

  • panel.v2 vs panel.ui: which namespace should we commit to?

Would adding panel.v2 coincide with a 2.0 release of Panel?

How aggressively should we deprecate legacy widgets once panel.v2 stabilizes?

I am of the opinion that the legacy widgets should all eventually be deprecated and removed.

Introduce label ↔ name compatibility

Similarly, I'd like name to be deprecated at some point if label is introduced.

maximlt avatar Dec 05 '25 10:12 maximlt

And to build on that point and agreeing with Marc "it even harder to understand api differences", I think it should be clear to new users the one way to do things and not mix and match them, so I propose a huge major release instead, while in the meantime, providing FutureWarnings on pn.extension() to pin panel<2 for current users

I have to admit, I don't quite understand what the proposal here is. What would trigger a future warning?

Would adding panel.v2 coincide with a 2.0 release of Panel?

No, I think it'd coincide with a 1.9 release, and we'd make it the default for 2.0. That I guess raises the question whether we also introduce pn.legacy as the inverse.

I am of the opinion that the legacy widgets should all eventually be deprecated and removed.

Fully agreed.

Similarly, I'd like name to be deprecated at some point if label is introduced.

Indeed, sorry I didn't state that explicitly.

philippjfr avatar Dec 05 '25 10:12 philippjfr

Great news and thank you for your amazing work everyone!!!

Could Panel 2.0 support the no GIL Python versions being released so we can have more complex object lifecycle (before created, before render, etc.) much like the OpenLayers and other JavaScript libraries. This way it will be easier to implement observers and life cycle hooks.

Could we get something like Vue's Pinia store to make state management easier?

As you can see most of my suggestions are about decreasing friction with JavaScript libraries (OpenLayers, Plotly, Bokeh etc.) because I feel like the hvPlot strategy of having a one liner all the way to accessing the underlying Javascript object and CSS could also apply to Panel to create Data Apps. .ost people just beed a panel for a leaflet map and some interactive element but Panel 2.0 can also interact with OpenLayers for an iframe whose events are handled by the pytbon panel side and can have sys calls and IO operations in the callbacks.

Just dreaming here but I'm a huge fan of everything you're doing (Datashader, Param, Bokeh, Geoviews etc.).

itsgifnotjiff avatar Dec 06 '25 18:12 itsgifnotjiff

  • panel.v2 vs panel.ui: which namespace should we commit to?

Looking at the long term, which of those 2 is the optimal choice in terms of managing future migrations after v2?

So does .v2 or .ui work better as a starting point, when it is time to migrate to v3 (or v2.5)?

Same question for subsequent migrations. Does panel.v(x), panel.v.(x), or panel.ui work better for migrations, backwards compatibility etc.?

Or is there no real advantage either way?

Coderambling avatar Dec 06 '25 18:12 Coderambling

Could also be called .experimental.

Streamlit usd a namespace like that to make it very clear that things might change or get removed again.

MarcSkovMadsen avatar Dec 07 '25 02:12 MarcSkovMadsen

Some quick comments focusing on the migration itself and not the technical part of it. From a technical standpoint, I agree with Marc that it should work with modern tooling.


As Panel continues to evolve its UI and widget ecosystem, we want to define a clear, intentional migration path toward integrating the work in panel-material-ui into core Panel.

Do you want to move panel-material-ui code merge into panel itself or do you want panel to depend on panel-material-ui?


I agree, with Maxime that a flat namespace is a not ideal, but not sure how if it should work pn.v2.{widgets, chat, pane} / pn.{widgets, chat, pane}.v2 (v2 used an example here, but could be something else).


How aggressively should we deprecate legacy widgets once panel.v2 stabilizes?

I don't think we should be very aggressive, and we definitely want to keep both for a long time; something doesn't translate well between v1 / v2. More so, design is very subjective, even though v2 looks prettier out of the box, who is to say someone does not prefer v1 and has applied a lot of customization to make it pretty?

I'm also not a fan of "legacy", I think it has a negative tone to it, not sure what it should be instead, maybe "classic".

hoxbro avatar Dec 09 '25 14:12 hoxbro

I don't think we should be very aggressive, and we definitely want to keep both for a long time; something doesn't translate well between v1 / v2. More so, design is very subjective, even though v2 looks prettier out of the box, who is to say someone does not prefer v1 and has applied a lot of customization to make it pretty?

I don't share that opinion, I believe we're already suffering quite a bit from "having too many ways to achieve the same thing" and I am not excited about having two competing collections of components.

Do we have a way to see how compatible Panel and PMUI widgets are? For example, which of the current options of the pn.widgets.Select widgets are also supported by pmui.widgets.Select?

maximlt avatar Dec 09 '25 17:12 maximlt

I have to admit, I don't quite understand what the proposal here is. What would trigger a future warning?

The proposed FutureWarning would be raised whenever pn.extension() is called under Panel 1.x, without explicitly calling pn.extension("classic") or something similar.

So: pn.extension(): Emit FutureWarning(“Panel 2.0 will change the default UI backend. Pin panel<2 in requirements.txt or explicitly request pn.extension("classic") to maintain current behaviour.”)

pn.extension("material"): No warning. The user is explicitly opting into the new system.

pn.extension() with export PANEL_CLASSIC = 1 set: No warning. This acts as a compatibility flag for environments that want to explicitly freeze classic behaviour without changing all code paths.

Basically, the warning would signal “major breaking release ahead—please pin your version now.”

ahuang11 avatar Dec 09 '25 17:12 ahuang11

@ahuang11 I think based on previous discussion the pn.extension mechanism for switching was rejected.

I don't share that opinion, I believe we're already suffering quite a bit from "having too many ways to achieve the same thing" and I am not excited about having two competing collections of components.

I agree with this, deprecation should happen and we should strongly recommend that people switch. We can't make everyone happy all the time.

Do we have a way to see how compatible Panel and PMUI widgets are? For example, which of the current options of the pn.widgets.Select widgets are also supported by pmui.widgets.Select?

We did some of this before releasing panel-material-ui in the first place. For the most part the compatibility is very complete, though there are some exceptions. We'd definitely want to make another attempt at checking compatibility thoroughly.

philippjfr avatar Dec 17 '25 14:12 philippjfr

I read the roadmap update which helped me understand better the suggested migration path. It says at the end that for Panel 3.0:

Theme: Modern-by-default

  • panel.ui becomes the primary and recommended API surface.
  • panel.layout, panel.pane, and panel.widgets are formally deprecated and may be removed
  • ...

What users should do

  • Ensure applications have migrated to panel.ui.
  • ...

So, while it doesn't guarantee the current component APIs will ultimately be removed ("may be removed"), the idea is that all users are expected to migrate to the new namespace (v2 or ui, name to be decided). I did not understand at first. I thought that the namespace was just meant to be temporary (probably understood it this way as v2 means it's attached to version 2 of Panel, which is temporary). I'm not super enthusiastic about the thought of every Panel app code base in the world having to be updated 🤔.

For the most part the compatibility is very complete, though there are some exceptions. We'd definitely want to make another attempt at checking compatibility thoroughly.

PMUI has been designed to be very compatible with the current Panel components which is great! Doesn't that open the door for the current components to be swapped with their PMUI counterpart, as suggested by Andrew?

I haven't yet updated any app to PMUI so don't have personal feedback on how easy it is to migrate. I don't think we have data about the percentage of Panel apps that could be migrated without change to PMUI. How many of the apps in the App Gallery would just work if they were using PMUI instead of Panel without any other change?


I think based on previous discussion the pn.extension mechanism for switching was rejected.

Maybe this has been rejected too quickly? I might agree that this is not ideal, it's all a tradeoff, and a new namespace isn't ideal either. It might not be THE way that Panel will provide to migrate, but it could still be an easy way for users to try out PMUI without having to update their code base in all the places they create a component.

As a user, I would like to be provided with some support to migrate:

  1. A complete user migration guide, listing all the gotchas
  2. Ideally, with tools that help me migrate my apps (from reporting tools, to a magical panel migrate command)

I consider pn.extension() could be one of these tools.

maximlt avatar Dec 17 '25 16:12 maximlt