React Template layout

Hello community,

I am relatively new to Panel, and I’m struggling to understand how to configure objects to lay out my components in the way that I want.

I’m using the react template, and I’m getting unexpected behavior (in my mind, at least) when I assign objects to the main grid. Perhaps I’m misunderstanding how the react template works, but I expected that something like

pn.extension(sizing_mode='stretch_both')  
react = pn.template.ReactTemplate()  
react.main[:, :6] = obj1  
react.main[:, 6:] = obj2

would place obj1 and obj2 in a single row across 6 columns each. However, in practice, these elements sometimes get stacked on top of one another in two rows. See the below minimal example where simply toggling the sidebar between collapsed states causes the objects to reorient in the react grid.

import numpy as np
import pandas as pd
import holoviews as hv
import panel as pn
import param

hv.extension('bokeh')
pn.extension(sizing_mode = 'stretch_both')

class Test(param.Parameterized):
    df = param.DataFrame()
    
    def __init__(self, **params):
        super(Test, self).__init__(**params)
        self.plot()
    
    def plot(self):
        N = 8
        node_indices = np.arange(N, dtype=np.int32)
        source = np.zeros(N, dtype=np.int32)
        target = node_indices
        simple_graph = hv.Graph(((source, target),))
        
        return simple_graph.opts(responsive=True)
        

test = Test(df=pd.DataFrame([np.random.randint(0, 100, size=25), np.random.randint(0, 100, size=25)], columns = range(25), index = ['x', 'y']))

react = pn.template.ReactTemplate()
react.sidebar.append(pn.Column())
react.main[:, :6] = test.plot
react.main[:, 6:] = pn.Param(test, parameters = ['df'], widgets = {'df': {'fit_columns': True, 'sizing_mode': 'stretch_both', 'autosize_mode':'fit_columns'}})
react.show()

Can anyone help me better understand how to work with laying out objects in the react grid and controlling their responsive properties (i.e. width, height, aspect, etc.).

Thanks!!

Hi @mak4515 and welcome :slight_smile:

Not a template expert here, but I’m not so surprised by this behaviour. You can see on this react grid showcase website that when you resize your window the elements get stacked (row-wise or colomun-wise depending on how you resize the window).

The React template has an optional cols parameter that allows you to determine the number of columns with respect to the layout size (lg for large, md for medium…). You can define a unique value for all the sizes, which in your case will effectively prevent your two elements for being stacked in a column:

react = pn.template.ReactTemplate(
    cols={'lg': 12, 'md': 12, 'sm': 12, 'xs': 12, 'xxs': 12}
)

I guess though that there is more to say about how to control the behavior of the grid :upside_down_face:

1 Like

I think the solution you propose @maximlt is the right one. But @nghenzi is probably the expert.

I tried giving the code an iteration the way I would work with it and using the FastGridTemplate.

import numpy as np
import pandas as pd
import holoviews as hv
import panel as pn
import param

pn.extension(sizing_mode="stretch_both")
hv.extension("bokeh")

_COLORS = [
    ("#00A170", "white"),
    ("#DAA520", "white"),
    ("#2F4F4F", "white"),
    ("#F08080", "white"),
    ("#4099da", "white"),  # lightblue
]
ACCENT_BASE_COLOR, _ = _COLORS[-2]


class Test(param.Parameterized):
    df = param.DataFrame()

    def __init__(self, **params):
        super(Test, self).__init__(**params)
        self.plot()

    def plot(self):
        N = 8
        node_indices = np.arange(N, dtype=np.int32)
        source = np.zeros(N, dtype=np.int32)
        target = node_indices
        simple_graph = hv.Graph(((source, target),))

        return simple_graph.opts(responsive=True, node_color=ACCENT_BASE_COLOR)


test = Test(
    df=pd.DataFrame(
        [np.random.randint(0, 100, size=25), np.random.randint(0, 100, size=25)],
        columns=range(25),
        index=["x", "y"],
    )
)

react = pn.template.FastGridTemplate(
    row_height=400, cols={"lg": 12, "md": 12, "sm": 12, "xs": 12, "xxs": 12},
    header_background=ACCENT_BASE_COLOR,
    accent_base_color=ACCENT_BASE_COLOR,
    prevent_collision=True,
    save_layout=True,
)
react.sidebar.append(pn.Column("# Settings"))
react.main[:, :6] = test.plot
react.main[:, 6:] = pn.Param(
    test,
    parameters=["df"],
    widgets={
        "df": {
            "fit_columns": True,
            "min_height": 500,
            "sizing_mode": "stretch_both",
            "autosize_mode": "fit_columns",
        }
    },
)
react.servable()

You can find a video walk through of the FastGridTemplate here https://youtu.be/_mv9xwwzWAA. It provides the same features as the ReactTemplate and then some.

great ! It works like a charm !!!

1 Like

Thank you all for your timely replies! This clears things up significantly. @maximlt I read about the cols option in the documentation but its description didn’t make sense until now.

@Marc Thank you for giving the code a go with the FastGridTemplate–I think I’ll switch to using this template instead since it seems to have some really convenient additional features.

As a final general question about layouts, are there any good resources or examples showing how combining different sizing modes across different panel elements and/or widgets affects their ultimate visual properties? I recognize that this question is quite broad, but any suggestions would be greatly appreciated!

@Marc This looks like an amazing resource! Thanks! I’ll definitely be giving it a watch in the near future.

1 Like