Positioning things alongside tab buttons to free up wasted space?

I’ve got two elements in a column and one of those elements is a set of tabs. One of the tabs has a figure that’s important to display as big as possible, so I’m trying to figure out how I can make the tab buttons take up less space, or otherwise free up vertical space for the figure.

Is there any way to make tab buttons a little less obtrusive? Maybe selecting the tabs could be controlled in some other way intuitive to viewers?

Here’s a minimal example to demonstrate:

from bokeh.models import Panel, Tabs, Div
from bokeh.plotting import figure, output_file, show
from bokeh.layouts import column

output_file("slider.html")

p1 = figure(sizing_mode="stretch_both")
p1.circle([1, 2, 3, 4, 5], [6, 7, 2, 4, 5], size=20)
tab1 = Panel(child=p1, title="move these buttons")

p2 = figure(sizing_mode="stretch_both")
p2.line([1, 2, 3, 4, 5], [6, 7, 2, 4, 5], line_width=3)
tab2 = Panel(child=p2, title="to top right?")

area = Div(text="<p><strong>Can we put tab buttons at this height alongside other things to remove wasted vertical space?</strong></p>", width=1400)
tabs = Tabs(tabs=[tab1, tab2])
show(column(area, tabs))

Hi @tvkyq

I think you mostly have to work within the grid-like layout schemes available.

For your minimal example, what if you change the last few lines to the following, i.e. use a row-wise layout with a narrower div (w=200px vs 1400px, for example).

area = Div(text="<p><strong>Can we put tab buttons at this height alongside other things to remove wasted vertical space?</strong></p>", width=200)
tabs = Tabs(tabs=[tab1, tab2])
show(row(area, tabs))


There are spacers available via bokeh.models.Spacer() that can offer some amount of flexibility in the layout. Perhaps, these simple suggestions do not meet the requirements in your ultimate use case, but just thought I’d mention.

Thank you @_jm. This would’ve be helpful for the example I provided but I should’ve mentioned it’s especially important to make the figure as wide as possible, so this wouldn’t suit my specific needs.

I might be close to a workaround. If I manually set the top_area_height the tabs will use the additional space, but the div still renders in the smallest area it can, which is a height greater than top_area_height, and things are displayed on the same level:

from bokeh.models import Panel, Tabs, Div, Select
from bokeh.plotting import figure, output_file, show
from bokeh.layouts import column, row

output_file("slider.html")

p1 = figure(sizing_mode="stretch_both")
p1.circle([1, 2, 3, 4, 5], [6, 7, 2, 4, 5], size=20)
tab1 = Panel(child=p1, title="move these buttons")

p2 = figure(sizing_mode="stretch_both")
p2.line([1, 2, 3, 4, 5], [6, 7, 2, 4, 5], line_width=3)
tab2 = Panel(child=p2, title="to top right?")

top_area_height=25
div = Div(text="<p><strong>Can we put tab buttons at this height alongside other things to remove wasted vertical space?</strong></p>", width=620, height=top_area_height)
select = Select(title="bottom of select tool unresponsive", value='try clicking this', options=['try clicking this', 'try clicking this'], height=top_area_height)
filler = Div(text="", width=400, height=top_area_height)

tabs = Tabs(tabs=[tab1, tab2])
show(column(row(div, select, filler), tabs))

There are two issues:

  • widgets are unresponsive across the area that would’ve otherwise been wasted by the tab buttons
  • there doesn’t seem to be a way to align the tabs to the right. Tabs has align which seems to only be useful for row / column arrangements, and tabs_location, but that doesn’t seem to work either because entering ‘right’ puts the buttons to the right of the figure and justified to the top, and we want the buttons above the figure and justified to the right.

Does anyone know how to fix either?

There is a margin property of Div, which by default is the tuple (5,5,5,5). You might be able to reclaim some pixels by choosing 0 or other-than-default values for some of the elements therein.