Ran into some issues being able to get a more expressive full-screen layout. AI / Claude notes for things that can be improved with the grid / layout:
Layout improvement notes
Collected while doing a design pass on docs/examples/fullscreen-dashboard.ipynb
(a controls-rail + lonboard-map + chart layout inside Fullscreen). Observations
only — none of this is implemented. Ordered roughly by impact.
1. Grid: equal columns only
grid/widget.py has columns = traitlets.Int(2) and grid/src/index.ts hard-codes
repeat(N, minmax(0, 1fr)). There is no way to express the most common dashboard
shape — a narrow control rail beside a wide map (320px 1fr), or a cell spanning
two columns. The workaround in the example (put the chart in the rail so the 50/50
split doesn't leave a dead half-column) works but shouldn't be necessary.
Smallest fix: widen columns to Union([Int(), Unicode()]); when it's a string,
pass it straight through to gridTemplateColumns. ~4 lines across widget.py and
index.ts. Spans would need a per-child wrapper or a spans=[...] trait — bigger
API question.
2. Chart: fixed pixel width only
Chart.width is Int (px). .manywidgets-chart has max-width: 100%, so a chart
can shrink but never fill a wider container. The example exploits this by
oversizing (width=1100 → the column caps it), which works because Chart.js is
responsive: true — but it's a non-obvious trick. Supporting width=None (or
"100%") meaning fill-container would make charts compose into layouts naturally.
Same question applies to height eventually (fill a fixed-height cell).
3. Row/Column: no justify, no per-child sizing
row/, column/ expose only gap and align. Cells are flex: 0 1 auto with no
way to set grow/basis per child, so a Row collapses children without intrinsic
width (lonboard maps — already noted in docs/examples/layout.ipynb). A justify
trait and some per-child flex control (Row(a, b, flex=[0, 1])?) would cover most
gaps; until then Grid is the only reliable side-by-side container.
4. FilterBinder chip / LayerToggle theming
FilterBinder renders a status chip styled via inline el.style.cssText
(lonboard/filter_binder/src/index.ts) — unoverridable, no visible/compact
trait, and it must stay mounted for static export. In a polished dashboard it
reads as debug output. A show_status=False mode that renders (say) a 0-height
element while keeping the JS alive would fix it.
lonboard/layer_toggle never calls applyThemeVars and hardcodes its colors
and sizes, so it ignores theme=/style= and the --mw-toggle-* tokens the
core Toggle honors. Visually inconsistent next to themed controls.
5. Fullscreen: alt layout can't opt into fill-height
Only the no-alt slot path gets the stretch rules (.mwfs__content > .mwfs__slot);
a fullscreen= layout is height: auto and the panel scrolls. Fine as a default,
but a dashboard usually wants "fill the screen, no scroll" — some opt-in (or a
documented height="70vh"-style recipe, which is what the example uses) would
help. Also the overlay's padding: 24px is hardcoded in fullscreen/style.css
where the panel padding is already tokenized — could be a --mw-* token too.
6. Fixed widget margins
Nearly every widget wrapper carries margin: 10px 0 in its own style.css.
Containers can only add space (gap), never remove it, so tight layouts bottom
out at ~20px rhythm. A --mw-widget-margin token (or containers zeroing child
margins and owning spacing via gap) would give real control.
Aside: what DOES compose well today
style= on any themable widget cascades --mw-* tokens to descendants across
shadow boundaries — e.g. Fullscreen(..., style={"--mw-control-max-width": "100%"})
retunes every control card inside the overlay in one place. This is a genuinely
good lever; worth documenting more prominently in the theming guide.
---- end AI notes -----
@dzole0311 I think some of the flexbox stuff, etc. is beyond me to know exactly what we should do here. Most of the AI notes make sense, but would like to get a sanity check if these seem sensible to do or if we should re-look at some of the grid / layout stuff in a more fundamental way.
Ran into some issues being able to get a more expressive full-screen layout. AI / Claude notes for things that can be improved with the grid / layout:
Layout improvement notes
Collected while doing a design pass on
docs/examples/fullscreen-dashboard.ipynb(a controls-rail + lonboard-map + chart layout inside
Fullscreen). Observationsonly — none of this is implemented. Ordered roughly by impact.
1. Grid: equal columns only
grid/widget.pyhascolumns = traitlets.Int(2)andgrid/src/index.tshard-codesrepeat(N, minmax(0, 1fr)). There is no way to express the most common dashboardshape — a narrow control rail beside a wide map (
320px 1fr), or a cell spanningtwo columns. The workaround in the example (put the chart in the rail so the 50/50
split doesn't leave a dead half-column) works but shouldn't be necessary.
Smallest fix: widen
columnstoUnion([Int(), Unicode()]); when it's a string,pass it straight through to
gridTemplateColumns. ~4 lines across widget.py andindex.ts. Spans would need a per-child wrapper or a
spans=[...]trait — biggerAPI question.
2. Chart: fixed pixel width only
Chart.widthisInt(px)..manywidgets-charthasmax-width: 100%, so a chartcan shrink but never fill a wider container. The example exploits this by
oversizing (
width=1100→ the column caps it), which works because Chart.js isresponsive: true— but it's a non-obvious trick. Supportingwidth=None(or"100%") meaning fill-container would make charts compose into layouts naturally.Same question applies to
heighteventually (fill a fixed-height cell).3. Row/Column: no justify, no per-child sizing
row/,column/expose onlygapandalign. Cells areflex: 0 1 autowith noway to set grow/basis per child, so a
Rowcollapses children without intrinsicwidth (lonboard maps — already noted in
docs/examples/layout.ipynb). Ajustifytrait and some per-child flex control (
Row(a, b, flex=[0, 1])?) would cover mostgaps; until then Grid is the only reliable side-by-side container.
4. FilterBinder chip / LayerToggle theming
FilterBinderrenders a status chip styled via inlineel.style.cssText(
lonboard/filter_binder/src/index.ts) — unoverridable, novisible/compacttrait, and it must stay mounted for static export. In a polished dashboard it
reads as debug output. A
show_status=Falsemode that renders (say) a 0-heightelement while keeping the JS alive would fix it.
lonboard/layer_togglenever callsapplyThemeVarsand hardcodes its colorsand sizes, so it ignores
theme=/style=and the--mw-toggle-*tokens thecore
Togglehonors. Visually inconsistent next to themed controls.5. Fullscreen: alt layout can't opt into fill-height
Only the no-alt slot path gets the stretch rules (
.mwfs__content > .mwfs__slot);a
fullscreen=layout isheight: autoand the panel scrolls. Fine as a default,but a dashboard usually wants "fill the screen, no scroll" — some opt-in (or a
documented
height="70vh"-style recipe, which is what the example uses) wouldhelp. Also the overlay's
padding: 24pxis hardcoded infullscreen/style.csswhere the panel padding is already tokenized — could be a
--mw-*token too.6. Fixed widget margins
Nearly every widget wrapper carries
margin: 10px 0in its own style.css.Containers can only add space (
gap), never remove it, so tight layouts bottomout at ~20px rhythm. A
--mw-widget-margintoken (or containers zeroing childmargins and owning spacing via gap) would give real control.
Aside: what DOES compose well today
style=on any themable widget cascades--mw-*tokens to descendants acrossshadow boundaries — e.g.
Fullscreen(..., style={"--mw-control-max-width": "100%"})retunes every control card inside the overlay in one place. This is a genuinely
good lever; worth documenting more prominently in the theming guide.
---- end AI notes -----
@dzole0311 I think some of the flexbox stuff, etc. is beyond me to know exactly what we should do here. Most of the AI notes make sense, but would like to get a sanity check if these seem sensible to do or if we should re-look at some of the grid / layout stuff in a more fundamental way.