File size: 3,681 Bytes
12cdb17 9ac8f1c 12cdb17 9ac8f1c 1b16c40 12cdb17 1b16c40 9ac8f1c 12cdb17 9ac8f1c 12cdb17 1b16c40 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 | """Catppuccin Plotly template installer."""
import plotly.graph_objects as go
import plotly.io as pio
import streamlit as st
from catppuccin import PALETTE
def active_base() -> str:
"""Return the live theme flavor ("light"/"dark").
Reflects the user's choice in Streamlit's built-in Settings-menu theme
toggle, falling back to the configured ``theme.base`` default.
"""
return st.context.theme.type or st.get_option("theme.base")
def _flavor(base: str | None):
return PALETTE.latte if base == "light" else PALETTE.mocha
def install_catppuccin_theme(base: str | None = None) -> None:
"""Register a Catppuccin template and alias it as ``plotly_white``.
Call once at startup. Persona-vectors pins ``template="plotly_white"`` on
every figure, so replacing that entry themes all plots without any
per-figure code.
"""
c = _flavor(base).colors
bg, text, subtext = c.base.hex, c.text.hex, c.subtext1.hex
if base == "light":
# Latte's surface0/1 are heavy grays; use lighter slots so the grid
# stays subtle, the legend isn't a gray block, and diverging plots
# fade through near-white instead of mud.
surface, line, mid = c.mantle.hex, c.surface0.hex, c.base.hex
else:
surface, line, mid = c.surface0.hex, c.surface1.hex, c.surface0.hex
axis = dict(
gridcolor=line,
zerolinecolor=line,
linecolor=line,
tickcolor=line,
tickfont=dict(color=subtext),
title=dict(font=dict(color=text)),
)
scene_axis = dict(
backgroundcolor=bg,
gridcolor=line,
zerolinecolor=line,
showbackground=True,
color=text,
tickfont=dict(color=subtext),
)
template = go.layout.Template(
layout=dict(
paper_bgcolor=bg,
plot_bgcolor=bg,
font=dict(color=text),
colorway=[
c.blue.hex,
c.mauve.hex,
c.green.hex,
c.peach.hex,
c.teal.hex,
c.pink.hex,
c.yellow.hex,
c.sapphire.hex,
c.lavender.hex,
c.red.hex,
c.sky.hex,
c.maroon.hex,
],
xaxis=axis,
yaxis=axis,
scene=dict(xaxis=scene_axis, yaxis=scene_axis, zaxis=scene_axis),
legend=dict(bgcolor=surface, bordercolor=line, font=dict(color=text)),
colorscale=dict(
diverging=[[0.0, c.blue.hex], [0.5, mid], [1.0, c.red.hex]],
),
)
)
pio.templates["catppuccin"] = template
pio.templates["plotly_white"] = template
pio.templates.default = "catppuccin"
def style_plotly_layer_controls(fig: go.Figure, base: str | None = None) -> go.Figure:
"""Theme persona-vectors layer sliders/buttons for this Streamlit app."""
c = _flavor(base).colors
surface = c.surface0.hex
overlay = c.surface1.hex
text = c.text.hex
primary = c.blue.hex
for slider in fig.layout.sliders:
slider.bgcolor = surface
slider.activebgcolor = primary
slider.bordercolor = overlay
slider.borderwidth = 1
slider.font = dict(color=text, size=11)
slider.tickcolor = primary
slider.currentvalue = dict(
slider.currentvalue.to_plotly_json(),
font=dict(color=text, size=13),
)
for menu in fig.layout.updatemenus:
if menu.type != "buttons":
continue
menu.bgcolor = surface
menu.bordercolor = overlay
menu.font = dict(color=text, size=13)
return fig
|