Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
124 changes: 92 additions & 32 deletions skills/panel-material-ui/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,6 @@ class HelloWorld(pn.viewable.Viewer):
self._outputs = pmui.Column(self.model)
self._panel = pmui.Row(self._inputs, self._outputs)


# DO use caching to speed up bound methods that are expensive to compute or load data and return the same result for a given state of the class.
@pn.cache
# DO prefer .depends over .bind over .rx for reactivity methods on Parameterized classes as it can be typed and documented
Expand Down Expand Up @@ -164,7 +163,81 @@ def test_characters_reactivity():
- DO use Material UI `sx` parameter for all css styling over `styles` and `stylesheets`
- DO use panel-material-ui components instead of panel components for projects already using panel-material-ui and for new projects
- DON'T configure the `design`, i.e. DO NOT `pn.extension(design='material')`.
- DO prefer professional Material UI icons over emojies
- DO prefer professional Material UI icons over emojis

## Theming and Styling

Panel Material UI supports four styling layers:

- **`theme_config`**: App-wide theme for palette, typography, shape, and defaults. Prefer this for consistent styling across a page or app.
- **`sx`**: Local Material UI styling for a specific component, including nested Mui selectors and dark/light mode overrides.
- **`styles`**: Styles the outer Panel container, useful for spacing, borders, backgrounds, and shadows around a component.
- **`stylesheets`**: Custom CSS selectors for classic Panel internals. Use sparingly.

**Recommended order of use:** prefer `theme_config` for global consistency, use `sx` for local component-level exceptions, use `styles` for outer container layout/styling, and reserve `stylesheets` for cases not covered by the other options.

### `sx`

- DO use `sx` for one-off component styling and nested Mui element overrides.
- DO use selectors like `& .MuiSlider-thumb` to target internal Material UI parts when needed.
- DO use `.mui-dark` and `.mui-light` selectors for mode-specific local styling.
- DON'T rely heavily on nested Mui class names unless necessary, as they may change across versions.

### `theme_config`

- DO use `theme_config` for app-wide palette, typography, shape, and component defaults.
* DO define `theme_config` at a top-level container such as `Page`, `Row`, `Column`, or `Card` so it inherits to children.
* DO use `"light"` and `"dark"` keys when separate light and dark themes are needed.
* DO prefer `theme_config` over repeated `sx` values when the same visual language should apply across the app.

### `styles`

* DO use `styles` for the outer wrapper box only.
* DO use it for spacing, borders, backgrounds, border radius, and shadows around a component.
* DON'T use `styles` when you actually want to style the internal Mui control; use `sx` instead.

### Styling Guidance

* DO use `sizing_mode` for layout behavior before reaching for CSS sizing in `sx`.
* DO use `sx` for Material UI component internals.
* DO use `theme_config` for consistency and maintainability.
* DO use `styles` only for wrapper-level styling.
* DO use `stylesheets` only when `sx`, `theme_config`, and `styles` are insufficient.

### Example Pattern

```python
app_theme = {
"light": {
"palette": {"primary": {"main": "#6a1b9a"}},
"shape": {"borderRadius": 12},
},
"dark": {
"palette": {"primary": {"main": "#9575cd"}},
"shape": {"borderRadius": 12},
},
}

button_sx = {
"fontWeight": 700,
"&:hover": {"transform": "scale(1.02)"},
}

container_styles = {
"padding": "8px",
"background": "rgba(0,0,0,0.02)",
}

pmui.Page(
main=[
pmui.Paper(
pmui.Button("Submit", color="primary", sx=button_sx),
styles=container_styles,
)
],
theme_config=app_theme,
)
```

## Component Instructions

Expand Down Expand Up @@ -198,34 +271,6 @@ pmui.Page(
)
```

#### Linking Dashboard Theme with Page Theme

DO synchronize component themes with Page theme:

```python
...

dark_theme = param.Boolean(
doc="""True if the theme is dark""",
# To enable providing parameters and bound function references
allow_refs=True
)

@classmethod
def create_app(cls, **params):
"""Create app with synchronized theming."""
component = cls(**params)

page = pmui.Page(
...,
dark_theme=component.dark_theme, # Pass theme to Page
)

# Synchronize Page theme to component theme
component.dark_theme = page.param.dark_theme
return page
```

### Grid

- DO set `spacing=2` or higher to separate sub components in the grid.
Expand Down Expand Up @@ -278,6 +323,7 @@ pmui.Paper.param.margin.default=10
### Non-Existing Components

- Do use `Column` instead of `Box`. The `Box` component does not exist.
- Do use `TextInput` instead of `TextField`. The `TextField` component does not exist.

## Material UI Examples

Expand All @@ -295,6 +341,20 @@ pmui.Typography(
pmui.IconButton(icon=icon, disabled=True, ...)
```

### Icons in widget labels and options

DO embed icons directly in widget labels and options using the `:material/...:` token syntax:

```
pmui.Select(
label="Mode",
options=[
"Zoom :material/zoom:",
"Explore :material/explore@size=large,color=warning:",
],
)
```

### Static Components Pattern (Material UI)

```python
Expand All @@ -304,7 +364,7 @@ import param

pn.extension()

pmui.Paper.param.margin.default=10
pmui.Paper.param.margin.default = 10

class HelloWorld(pn.viewable.Viewer):
characters = param.Integer(default=10, bounds=(1, 100), doc="Number of characters to display")
Expand Down Expand Up @@ -350,4 +410,4 @@ if pn.state.served:
HelloWorld().servable()
```

**For all other Panel patterns (parameter-driven architecture, reactive updates, serving, etc.), refer tot the 'panel' skill.**
**For all other Panel patterns (parameter-driven architecture, reactive updates, serving, etc.), refer to the 'panel' skill.**
45 changes: 23 additions & 22 deletions skills/panel/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,30 +23,30 @@ Core dependencies provided with the `panel` Python package:

Optional panel-extensions:

- **panel-material-ui**: Modern Material UI components. To replace the panel native widgets within the next two years.
- **panel-material-ui**: Modern Material UI components. Will replace the panel native widgets within the next two years.
- **panel-graphic-walker**: Modern Tableau like interface. Can offload computations to the server and thus scale to large datasets.

Optional dependencies from the HoloViz Ecosystem:
Optional HoloViz ecosystem dependencies:

- **colorcet**: Perceptually uniform colormaps collection. Best for: scientific visualization requiring accurate color representation, avoiding rainbow colormaps, accessible color schemes. Integrates with hvPlot, HoloViews, Matplotlib, Bokeh.
- **datashader**: Renders large datasets (millions+ points) into images for visualization. Best for: big data visualization, geospatial datasets, scatter plots with millions of points, heatmaps of dense data. Requires hvPlot or HoloViews as frontend.
- **geoviews**: Geographic data visualization with map projections and tile sources. Best for: geographic/geospatial plots, map-based dashboards, when you need coordinate systems and projections. Built on HoloViews, works seamlessly with hvPlot.
- **holoviews**: Declarative data visualization library with composable elements. Best for: complex multi-layered plots, advanced interactivity (linked brushing, selection), when you need fine control over plot composition, scientific visualizations. More powerful but steeper learning curve than hvPlot.
- **holoviz-mcp**: Model Context Protocol server for HoloViz ecosystem. Provides access to detailed documentation, component search and agent skills.
- **hvplot**: High-level plotting API with Pandas `.plot()`-like syntax. Best for: quick exploratory visualizations, interactive plots from DataFrames/Xarray, when you want interactivity without verbose code. Built on HoloViews.
- **hvsampledata**: Shared datasets for the HoloViz projects.
* **hvPlot**: High-level interactive plotting for DataFrames and arrays.
* **HoloViews**: Composable, declarative visualizations for more advanced interactivity and plot composition.
* **Datashader**: Scalable rendering for very large datasets.
* **GeoViews**: Geospatial plotting with projections and map tiles.
* **colorcet**: Perceptually uniform, accessible colormaps.
* **holoviz-mcp**: Documentation, component search, and skill lookup tools for the HoloViz ecosystem.
* **hvsampledata**: Shared example datasets for HoloViz projects.

Optional dependencies from the wider PyData Ecosystem:
Optional wider PyData dependencies:

- **altair**: Declarative, grammar-of-graphics visualization library. Best for: statistical visualizations, interactive exploratory charts, when you need Vega-Lite's extensive chart gallery. Works well with Pandas/Polars DataFrames.
- **dask**: Parallel computing library for scaling Pandas DataFrames beyond memory. Best for: processing datasets larger than RAM, parallel computation across multiple cores/machines, lazy evaluation workflows.
- **duckdb**: High-performance analytical SQL database. Best for: fast SQL queries on DataFrames, aggregations on large datasets, when you need SQL interface, OLAP-style analytics. Much faster than Pandas for analytical queries.
- **matplotlib**: Low-level, highly customizable plotting library. Best for: publication-quality static plots, fine-grained control over every aspect of visualization, scientific plots, when you need pixel-perfect control.
- **pandas**: Industry-standard DataFrame library for tabular data. Best for: data cleaning, transformation, time series analysis, datasets that fit in memory. The default choice for most data work.
- **Plotly**: Interactive, publication-quality visualization library. Best for: 3D plots, complex interactive charts, animations, when you need hover tooltips and interactivity. Works well with Dash and Panel.
- **polars**: Modern, fast DataFrame library written in Rust. Best for: high-performance data processing, datasets that fit in memory but need speed, when you need lazy evaluation, better memory efficiency than Pandas.
- **xarray**: N-dimensional labeled arrays and datasets. Best for: multidimensional scientific data (climate, satellite imagery), data with multiple dimensions and coordinates, NetCDF/HDF5 files, geospatial raster data.
- **watchfiles**: Enables high performance file watching and autoreload for the panel server.
* **pandas**: Standard tabular data processing.
* **polars**: Faster, memory-efficient DataFrame processing.
* **duckdb**: Fast analytical SQL over local data and DataFrames.
* **dask**: Parallel and out-of-core computation for larger-than-memory workloads.
* **xarray**: Labeled N-dimensional arrays for scientific data.
* **Altair**: Declarative statistical visualization with Vega-Lite.
* **Plotly**: Rich interactive charts, including 3D and animation.
* **matplotlib**: Fine-grained static plotting.
* **watchfiles**: Fast file watching and autoreload for Panel development.

## Common Use Cases

Expand Down Expand Up @@ -222,7 +222,7 @@ DO fix any errors identified.
- DO use `param.Parameterized` or `pn.viewable.Viewer` classes to organize and manage state
- DO create widgets with `.from_param()` method. DON'T do this for panes, i.e. pn.pane.Str has no from_param method.
- DO use `@param.depends()` for reactive methods
- DO use `@param.depends(..., watch=True)` to update parameter/ state values and for side-effects like sending an email.
- DO use `@param.depends(..., watch=True)` to update parameter/ state values and for side-effects like logging.
- DO group related parameters in separate `Parameterized` or `Viewable` classes

```python
Expand Down Expand Up @@ -393,6 +393,7 @@ if __name__ == "__main__":
- **Defer load**: Defer load to after the app is shown to the user: `pn.extension(defer_load=True, loading_indicator=True, ...)`
- **Lazy-load components** using Tabs or Accordion for heavy content
- **Use caching** with `@pn.cache` decorator for expensive computations
- **Batch Updates** with `pn.io.hold()` as a decorator or context manager when updating multiple components at once.
- **Use async/await**: Implement asynchronous patterns for I/O operations
- **Use faster frameworks**: Replace slower Pandas with faster Polars or DuckDB
- **Offload to threads**: Consider using threading for CPU-intensive tasks
Expand Down Expand Up @@ -524,11 +525,11 @@ def kpi_value(self):

### Markdown

- DO set `Markdown.disable_anchors=True` to avoid page flickr when hovering over headers.
- DO set `Markdown.disable_anchors=True` to avoid page flicker when hovering over headers.

### Bind

- DON't bind a function to nothing: `pn.bind(some_func)`. Just run the function instead `some_func()`.
- DON'T bind a function to nothing: `pn.bind(some_func)`. Just run the function instead `some_func()`.

## Plotting

Expand Down