Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add ui.layout_columns() #856

Merged
merged 35 commits into from
Dec 12, 2023
Merged
Show file tree
Hide file tree
Changes from 33 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
ae514d1
use latest bslib with layout columns custom element
gadenbuie Dec 5, 2023
1fe3ee0
feat(layout_columns): Works and accepts `col_widths`
gadenbuie Dec 6, 2023
2f48831
feat(layout_columns): Support scalar integer for breakpoint
gadenbuie Dec 6, 2023
b154a26
feat(layout_columns): Support `row_heights` argument
gadenbuie Dec 6, 2023
57560fd
chore: Consolidate types
gadenbuie Dec 6, 2023
7c5116b
feat(layout_columns): Wrap children in .bslib-grid-item containers
gadenbuie Dec 6, 2023
42a7198
chore: Rename `ui.layout_columns_grid()`
gadenbuie Dec 6, 2023
fb3c9bd
feat: If singular `row_heights`, use value across all breakpoints
gadenbuie Dec 6, 2023
8713948
chore: Update bslib components.css
gadenbuie Dec 6, 2023
bf2e0d0
chore: make the formatters happy
gadenbuie Dec 6, 2023
9a797b7
refactor: row_heights code review
gadenbuie Dec 6, 2023
b08dc00
Merge remote-tracking branch 'origin/main' into feat/layout-columns-grid
gadenbuie Dec 6, 2023
3813018
rename: as_col_spec() and use intermediate object for happier pyright
gadenbuie Dec 7, 2023
ec09614
rename BreakpointsOptional type
gadenbuie Dec 7, 2023
2fb6f58
validate input to get down to one cast() call
gadenbuie Dec 7, 2023
7a6b70d
chore: update bslib deps again
gadenbuie Dec 8, 2023
3f8061e
feat: write col-widths-{break} attributes
gadenbuie Dec 8, 2023
d14912b
express: Add layout_columns_grid()
gadenbuie Dec 8, 2023
85c4c53
rename back to layout_columns
gadenbuie Dec 8, 2023
3510943
update bslib dependency
gadenbuie Dec 8, 2023
e2e521d
remove use of json module
gadenbuie Dec 8, 2023
7403ce6
docs(layout_columns): Document `layout_columns()`
gadenbuie Dec 8, 2023
2233d1c
Merge branch 'main' into feat/layout-columns-grid
gadenbuie Dec 8, 2023
c9b13ad
chore: remove unused import from example
gadenbuie Dec 11, 2023
eee050e
fix: Fix exporting of `layout_columns()` from `ui`
gadenbuie Dec 11, 2023
c693b65
Merge branch 'main' into feat/layout-columns-grid
gadenbuie Dec 11, 2023
5401af4
chore: update bslib deps
gadenbuie Dec 11, 2023
24a6cb5
avoid problematic type check for Python 3.9
gadenbuie Dec 11, 2023
3bc470f
chore: remove unused things
gadenbuie Dec 12, 2023
1e1f9c1
remove default page from express layout_columns
gadenbuie Dec 12, 2023
338f33f
relocate `as_col_spec()` and use Enum for breakpoints
gadenbuie Dec 12, 2023
8c36832
remove example app for now
gadenbuie Dec 12, 2023
67b0e0b
Merged origin/main into feat/layout-columns-grid
gadenbuie Dec 12, 2023
a646a11
remove newlines between parameter docs
gadenbuie Dec 12, 2023
eb5afc1
docs: Add item to changelog
gadenbuie Dec 12, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion scripts/htmlDependencies.R
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ versions <- list()
message("Installing GitHub packages: bslib, shiny, htmltools")
withr::local_temp_libpaths()
ignore <- capture.output({
pak::pkg_install(c("cran::bslib", "cran::shiny", "cran::htmltools"))
pak::pkg_install(c("rstudio/bslib", "cran::shiny", "cran::htmltools"))
#pak::pkg_install(c("rstudio/bslib@main", "rstudio/shiny@main", "rstudio/htmltools@main"))
})

Expand Down
2 changes: 1 addition & 1 deletion shiny/_versions.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
shiny_html_deps = "1.8.0"
bslib = "0.6.1"
bslib = "0.6.1.9000"
htmltools = "0.5.7"
bootstrap = "5.3.1"
requirejs = "2.3.6"
Expand Down
111 changes: 111 additions & 0 deletions shiny/express/layout.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

from .. import ui
from ..types import MISSING, MISSING_TYPE
from ..ui._layout_columns import BreakpointsUser
from ..ui.css import CssUnit
from . import _run
from ._recall_context import RecallContextManager, wrap_recall_context_manager
Expand All @@ -19,6 +20,7 @@
"pre",
"sidebar",
"layout_column_wrap",
"layout_columns",
"column",
"row",
"card",
Expand Down Expand Up @@ -206,6 +208,11 @@ def layout_column_wrap(
-------
:
A :class:`~htmltools.Tag` element.

See Also
--------
* :func:`~shiny.express.layout.layout_columns` for laying out elements into a
responsive 12-column grid.
"""
return RecallContextManager(
ui.layout_column_wrap,
Expand All @@ -225,6 +232,110 @@ def layout_column_wrap(
)


def layout_columns(
*,
col_widths: BreakpointsUser[int] = None,
row_heights: BreakpointsUser[CssUnit] = None,
fill: bool = True,
fillable: bool = True,
gap: Optional[CssUnit] = None,
class_: Optional[str] = None,
height: Optional[CssUnit] = None,
**kwargs: TagAttrValue,
):
"""
Create responsive, column-based grid layouts, based on a 12-column grid.

Parameters
----------
col_widths
cpsievert marked this conversation as resolved.
Show resolved Hide resolved
The widths of the columns, possibly at different breakpoints. Can be one of the
following:

* `None` (the default): Automatically determines a sensible number of columns
based on the number of children given to the layout.
* A list or tuple of integers between 1 and 12, where each element represents
the number of columns for the relevant UI element. Column widths are recycled
to extend the values in `col_widths` to match the actual number of items in
the layout, and children are wrapped onto the next row when a row exceeds 12
column units. For example, `col_widths=(4, 8, 12)` allocates 4 columns to the
first element, 8 columns to the second element, and 12 columns to the third
element (which wraps to the next row). Negative values are also allowed, and
are treated as empty columns. For example, `col_widths=(-2, 8, -2)` would
allocate 8 columns to an element (with 2 empty columns on either side).
* A dictionary of column widths at different breakpoints. The keys should be
one of `"xs"`, `"sm"`, `"md"`, `"lg"`, `"xl"`, or `"xxl"`, and the values are
either of the above. For example, `col_widths={"sm": (3, 3, 6), "lg": (4)}`.

row_heights
The heights of the rows, possibly at different breakpoints. Can be one of the
following:

* A numeric vector, where each value represents the
[fractional unit](https://css-tricks.com/introduction-fr-css-unit/)
(`fr`) height of the relevant row. If there are more rows than values
provided, the pattern will be repeated. For example, `row_heights=(1, 2)`
allows even rows to take up twice as much space as odd rows.
* A list of numeric or CSS length units, where each value represents the height
of the relevant row. If more rows are needed than values provided, the pattern
will repeat. For example, `row_heights=["auto", 1]` allows the height of odd
rows to be driven my it's contents and even rows to be
[`1fr`](https://css-tricks.com/introduction-fr-css-unit/).
* A single string containing CSS length units. In this case, the value is
supplied directly to `grid-auto-rows`.
* A dictionary of row heights at different breakpoints, where each key is a
breakpoint name (one of `"xs"`, `"sm"`, `"md"`, `"lg"`, `"xl"`, or `"xxl"`)
and where the values may be any of the above options.

fill
Whether or not to allow the layout to grow/shrink to fit a fillable container
with an opinionated height (e.g., :func:`~shiny.ui.page_fillable`).

fillable
Whether or not each element is wrapped in a fillable container.

gap
Any valid CSS unit to use for the gap between columns.

class_
CSS class(es) to apply to the containing element.

height
Any valid CSS unit to use for the height.

**kwargs
Additional attributes to apply to the containing element.

Returns
-------
:
An :class:`~htmltools.Tag` element.

See Also
--------
* :func:`~shiny.express.layout.layout_column_wrap` for laying out elements into a
uniform grid.

Reference
--------
* [Bootstrap CSS Grid](https://getbootstrap.com/docs/5.3/layout/grid/)
* [Bootstrap Breakpoints](https://getbootstrap.com/docs/5.3/layout/breakpoints/)
"""
return RecallContextManager(
ui.layout_columns,
kwargs=dict(
col_widths=col_widths,
row_heights=row_heights,
fill=fill,
fillable=fillable,
gap=gap,
class_=class_,
height=height,
**kwargs,
),
)


def column(width: int, *, offset: int = 0, **kwargs: TagAttrValue):
"""
Responsive row-column based layout
Expand Down
2 changes: 2 additions & 0 deletions shiny/ui/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
)

from ._layout import layout_column_wrap
from ._layout_columns import layout_columns


# Expose the following modules for extended usage: ex: ui.fill.as_fill_item(x)
Expand Down Expand Up @@ -185,6 +186,7 @@
"panel_sidebar",
"panel_main",
# _layout
"layout_columns",
"layout_column_wrap",
# _card
"CardItem",
Expand Down
5 changes: 5 additions & 0 deletions shiny/ui/_layout.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,11 @@ def layout_column_wrap(
-------
:
A :class:`~htmltools.Tag` element.

See Also
--------
* :func:`~shiny.ui.layout_columns` for laying out elements into a responsive
12-column grid.
"""
attrs, children = consolidate_attrs(*args, class_=class_, **kwargs)

Expand Down
Loading
Loading