I would like to have a common vertical y-axis label to the left of a grid of plots. With inspiration from the custom_attribution.py example that uses the new UI floating elements
argument I have tried to add a Panel
element to a Spacer
object of width 50px to the left of the grid
.
In the Panel
I have added transform: rotate(270deg);
to stylesheets
in order to have the text be shown in vertical layout.
I have styled the Spacer
with
:host(.spacer) {
display: flex;
justify-content: center;
align-items: center;
}
I can only get the label to show up if I use "parent"
as target
of the Node
used for position
in Panel
.
The label is always located in the upper left corner and horizontal. "center_left"
does not position the Panel
as expected.
If I in the browser developer panel deselect the following styles of div class="bk-Panel"
then the label shows up correctly (please see images below).
left: 0px;
top: 0px;
transform: translate(0%, -50%);
When deselecting bk-Panel
element styles:
I am probably doing something wrong with the use of Panel
and adding it to the Spacer
but my css
skills are limited. Can I accomplish what I would like to achieve?
Using Bokeh 3.4.0, Python 3.11.7, Firefox 124.0.1
import numpy as np
from bokeh.io import show
from bokeh.models import Node, Panel, Spacer, InlineStyleSheet
from bokeh.models.dom import HTML
from bokeh.plotting import figure
from bokeh.layouts import grid, row
def plot(N: int):
x = np.random.random(size=N) * 100
y = np.random.random(size=N) * 100
radii = np.random.random(size=N) * 1.5
colors = np.array(
[(r, g, 150) for r, g in zip(50+2*x, 30+2*y)],
dtype="uint8"
)
p = figure(
width = 300,
height = 300,
title=f"Plot with N={N} circles"
)
p.circle(
x = x,
y = y,
radius=radii,
fill_color=colors,
fill_alpha=0.6,
line_color=None
)
return p
def vertical_label(p, node_target, anchor):
label = Panel(
position=Node(target=node_target, symbol=anchor),
anchor=anchor,
stylesheets=["""
:host {
padding: 2px;
background-color: rgba(211, 211, 211, 0.7);
font-size: 12px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
transform: rotate(270deg);
z-index: 9;
}
"""],
elements=[
HTML("<b>Common label</b>"),
],
)
p.elements.append(label)
plts = []
for p in [100, 50, 300, 200]:
plts.append(plot(p))
g = grid(children = plts, ncols = 2)
stylesheet = InlineStyleSheet(
css = '''
:host(.spacer) {
display: flex;
justify-content: center;
align-items: center;
}
'''
)
s = Spacer(
width = 50,
css_classes = ['spacer'],
stylesheets=[stylesheet]
)
vertical_label(s, "parent", "center_left")
layout = row([s, g])
show(layout)