holoviz / panel

Panel: The powerful data exploration & web app framework for Python
https://panel.holoviz.org
BSD 3-Clause "New" or "Revised" License
4.42k stars 484 forks source link

Not easy to modify widths of Param widgets #5856

Open ahuang11 opened 7 months ago

ahuang11 commented 7 months ago
import param
import panel as pn
import holoviews as hv

class TestParam(param.Parameterized):

    a = param.Number(default=1, bounds=(0, 10))
    b = param.String(default="b")

hv_pane = pn.pane.HoloViews(hv.Curve([0, 1, 2]))
code = pn.pane.Markdown("""
pn.pane.HoloViews(hv.Curve([0, 1, 2]))
""")

pn.Row(
    pn.Tabs(
        ("Test1", pn.Param(TestParam, width=200)),
        ("Abcdefabcdef", pn.Param(TestParam, width=200)),
        tabs_location="left",
        width=250
    ),
    pn.Tabs(("Plot", hv_pane), ("Code", code)),
)

The widgets are cut off

image

More minimal:

import param
import panel as pn
import holoviews as hv

class TestParam(param.Parameterized):

    a = param.Number(default=1, bounds=(0, 10))
    b = param.String(default="b")

hv_pane = pn.pane.HoloViews(hv.Curve([0, 1, 2]))
code = pn.pane.Markdown("""abc""")

pn.Row(
    pn.Param(TestParam, width=150),
    pn.Tabs(("Plot", hv_pane), ("Code", code)),
)

Seems like slider respects width, but not TextInput

image
ahuang11 commented 7 months ago

Ok most minimal:

import param
import panel as pn

class TestParam(param.Parameterized):

    a = param.Number(default=1, bounds=(0, 10))
    b = param.String(default="b")

col = pn.Param(TestParam, width=100)
col
image
ahuang11 commented 7 months ago

Solution is to loop through all the widgets and set width manually

import param
import panel as pn
import holoviews as hv

class TestParam(param.Parameterized):

    a = param.Number(default=1, bounds=(0, 10))
    b = param.String(default="b")

col = pn.Param(TestParam, width=100)
for widget in col:
    widget.width = 100
col
image
hoxbro commented 7 months ago

An Alternative as posted in discourse, and re-posted below:

import param
import panel as pn
import holoviews as hv

pn.extension()

class TestParam(param.Parameterized):

    a = param.Number(default=1, bounds=(0, 10))
    b = param.String(default="b")

dd = {k: {"width": 100} for k in TestParam.param}
col = pn.Param(TestParam, width=100, widgets=dd)
col

I think this is a bug I would expect the width in pn.Column to be respected by the underlying widgets. A MRE:

import panel as pn

pn.extension()

pn.Column(
    pn.widgets.IntSlider(value=1),
    pn.widgets.TextInput(value="B"),
    width=100,
)

image

maximlt commented 7 months ago

What would you all think if Parameters would have a metadata attribute (like attrs) in which you could stuff something like metadata={'panel': {'width': 100'}}? A bit wordy but maybe less than having to pass kwargs to pn.Param or to use Widget.from_param(param_insta, **kwargs).

ahuang11 commented 7 months ago

Do you think there's other uses for metadata? If not, maybe just panel_kwargs for explicitness?

maximlt commented 7 months ago

panel_kwargs as the key in the metadata dict?

ahuang11 commented 7 months ago

I meant as the metadata dict itself (drop one layer of verbosity) panel_kwargs={'width': 100}

maximlt commented 7 months ago

Param is agnostic to Panel or any other framework, I don't think a panel_kwargs attribute is desirable.

ahuang11 commented 7 months ago

Maybe gui_kwargs then?

maximlt commented 7 months ago

I've already had the need for a metadata attribute (not related to Panel or any GUI) and have abused precedence instead, so I think I'd push more anyway for a generic metadata attribute. But precedence is a good example as is definitely has a GUI flavor. Let's get feedback from others!

ahuang11 commented 7 months ago

I see. If you already have a need for metadata attribute, then go with metadata > panel.

I was just concerned of over-designing it and having it too verbose for anyone to actually use.