import altair as alt
import panel as pn
from vega_datasets import data
pn.extension("vega", sizing_mode="stretch_width", template="fast")
In this example we will show how to style Vega and Altair charts with Panel supporting the default
and the dark
theme.
When we use the Fast templates the theme will be available from the query args
def get_theme():
return pn.state.session_args.get("theme", [b'default'])[0].decode()
theme=get_theme()
theme
Below we create some functionality to cycle through a list of nice accent colors.
nice_accent_colors = [
("#00A170", "white"), # Mint
("#DAA520", "white"), # Golden Rod
("#F08080", "white"), # Light Coral
("#4099da", "white"), # Summery Sky
("#2F4F4F", "white"), # Dark Slate Grey
("#A01346", "white"), # Fast
]
def get_nice_accent_color():
"""Returns the 'next' nice accent color"""
if not "color_index" in pn.state.cache:
pn.state.cache["color_index"]=0
elif pn.state.cache["color_index"]==len(nice_accent_colors)-1:
pn.state.cache["color_index"]=0
else:
pn.state.cache["color_index"]+=1
return nice_accent_colors[pn.state.cache["color_index"]]
accent_color, color = get_nice_accent_color()
pn.pane.Markdown(f"# Color: {accent_color}", background=accent_color, height=70, margin=0, style={"color": color, "padding": "10px"})
You can configure the style of vega
and vega-lite
via the config
key. Please note that only vega-lite
supports responsive behaviour by setting width
and height
to container
. vega
requires the width
and height
to be integers.
See Vega Themes and the Vega Themes Explorer App for more examples.
def get_vega_plot(theme="default", accent_color="blue"):
vegalite = {
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"description": "A simple bar chart with rounded corners at the end of the bar.",
"width": "container",
"height": "container",
"data": {
"values": [
{"a": "A", "b": 28},
{"a": "B", "b": 55},
{"a": "C", "b": 43},
{"a": "D", "b": 91},
{"a": "E", "b": 81},
{"a": "F", "b": 53},
{"a": "G", "b": 19},
{"a": "H", "b": 87},
{"a": "I", "b": 52}
]
},
"mark": {"type": "bar", "cornerRadiusEnd": 4, "tooltip": True},
"encoding": {
"x": {"field": "a", "type": "ordinal"},
"y": {"field": "b", "type": "quantitative"},
"color": {"value": accent_color},
}
}
if theme == "dark":
vegalite["config"] = {
"background": "#333",
"title": {"color": "#fff"},
"style": {"guide-label": {"fill": "#fff"}, "guide-title": {"fill": "#fff"}},
"axis": {"domainColor": "#fff", "gridColor": "#888", "tickColor": "#fff"},
}
return vegalite
vega_plot = get_vega_plot(theme=theme, accent_color=accent_color)
vega_pane = pn.pane.Vega(vega_plot, height=500, sizing_mode="stretch_both", name="VEGA")
vega_pane
You can select the theme of Altair plots using altair.themes.enable
and the color using the configure_mark
method.
For more details see the
def get_altair_plot(theme="default", accent_color="blue"):
if theme == "dark":
alt.themes.enable("dark")
else:
alt.themes.enable("default")
return (
alt.Chart(data.cars())
.mark_circle(size=200)
.encode(
x='Horsepower:Q',
y='Miles_per_Gallon:Q',
tooltip=["Name", "Origin", "Horsepower", "Miles_per_Gallon"],
)
.configure_mark(
color=accent_color
)
.properties(
height="container",
width="container",
)
.interactive()
)
altair_plot = get_altair_plot(theme=theme, accent_color=accent_color)
altair_pane = pn.pane.Vega(altair_plot, height=500, sizing_mode="stretch_both", name="ALTAIR")
altair_pane
Note how we mark this component .servable()
so that it shows up in our data app.
pn.Tabs(vega_pane, altair_pane).servable(title="Panel - Vega/ Altair with custom styling")
pn.state.template.param.update(accent_base_color=accent_color, header_background=accent_color)
You can serve the app via panel serve VegaAltairStyle.ipynb
and find it at http://localhost:5006/VegaAltairStyle. You should add the --autoreload
flag while developing for hot reloading.