Skip to content

feat(page_opts): Pass kwargs to underyling page function #1314

New issue

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

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

Already on GitHub? # to your account

Merged
merged 6 commits into from
Apr 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

* `shiny create` was updated to include some additional templates as well as an option to choose from the new [templates website](https://shiny.posit.co/py/templates/). (#1273, #1277, #1274)

* `shiny.express.ui.page_opts()` now accepts additional keyword arguments that are passed to the underlying page layout chosen by `shiny.ui.page_auto()`. (#1314)

### Bug fixes

* On Windows, Shiny Express app files are now read in as UTF-8. (#1203)
Expand Down
18 changes: 18 additions & 0 deletions shiny/api-examples/page_opts/app-express.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from shiny.express import ui

ui.page_opts(title="App with Navbar", fillable=True, id="page")

with ui.sidebar():
ui.input_select("data", "Dataset", ("tips", "flights", "exercise"))

with ui.panel_conditional("input.page === 'View'"):
ui.input_select("view", "View", ("plot", "table"))

ui.nav_spacer()

with ui.nav_panel("Data"):
"This page could be used to pick a dataset."

with ui.nav_panel("View"):
"This page could be used to view the dataset."
"Notice the additional controls that appear when 'View' is selected."
25 changes: 22 additions & 3 deletions shiny/express/ui/_page.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from htmltools import Tag

from ... import ui
from ..._docstring import no_example
from ..._docstring import add_example
from ...types import MISSING, MISSING_TYPE
from .._recall_context import RecallContextManager
from .._run import get_top_level_recall_context_manager
Expand All @@ -17,7 +17,7 @@ def page_auto_cm() -> RecallContextManager[Tag]:
return RecallContextManager(ui.page_auto)


@no_example()
@add_example()
def page_opts(
*,
title: str | MISSING_TYPE = MISSING,
Expand All @@ -26,11 +26,25 @@ def page_opts(
page_fn: Callable[..., Tag] | None | MISSING_TYPE = MISSING,
fillable: bool | MISSING_TYPE = MISSING,
full_width: bool | MISSING_TYPE = MISSING,
**kwargs: object,
) -> None:
"""
Set page-level options for the current app.

The arguments to this function get passed to :func:`~shiny.ui.page_auto`.
The arguments to this function get passed to :func:`~shiny.ui.page_auto`, which
determines which page function should be used based on the page options and the
top-level items in the app.

If there is a top-level :func:`~shiny.ui.nav_panel`, :func:`~shiny.ui.page_auto`
will use :func:`~shiny.ui.page_navbar`. Otherwise, if there is a top-level sidebar,
:func:`~shiny.ui.page_sidebar` is used.

If there are neither top-level nav panels nor sidebars, this will use the `fillable`
and `full_width` arguments to determine which page function to use:

1. If `fillable` is `True`, :func:`~shiny.ui.page_fillable` is used.
2. Otherwise, if `full_width` is `True`, :func:`~shiny.ui.page_fluid` is used.
3. If neither are `True`, :func:`~shiny.ui.page_fixed` is used.

Parameters
----------
Expand All @@ -57,6 +71,9 @@ def page_opts(
The page function to use. If ``None`` (the default), will automatically choose
one based on the arguments provided. If not ``None``, this will override all
heuristics for choosing page functions.
**kwargs
Additional arguments to pass to the page function. See the description above for
further details on how the page function is selected.
"""
try:
cm = get_top_level_recall_context_manager()
Expand All @@ -79,3 +96,5 @@ def page_opts(
cm.kwargs["fillable"] = fillable
if not isinstance(full_width, MISSING_TYPE):
cm.kwargs["full_width"] = full_width
if len(kwargs) > 0:
cm.kwargs.update(kwargs)
13 changes: 9 additions & 4 deletions shiny/ui/_page.py
Original file line number Diff line number Diff line change
Expand Up @@ -485,11 +485,16 @@ def page_auto(
"""
A page container which automatically decides which page function to use.

If there is a top-level nav, this will use :func:`~shiny.ui.page_navbar`. If not,
and there is a top-level sidebar, this will use :func:`~shiny.ui.page_sidebar`.
If there is a top-level :func:`~shiny.ui.nav_panel`, :func:`~shiny.ui.page_auto`
will use :func:`~shiny.ui.page_navbar`. Otherwise, if there is a top-level sidebar,
:func:`~shiny.ui.page_sidebar` is used.

If there are neither top-level navs nor sidebars, this will use the ``fillable`` and
``full_width`` arguments to determine which page function to use.
If there are neither top-level nav panels nor sidebars, this will use the `fillable`
and `full_width` arguments to determine which page function to use:

1. If `fillable` is `True`, :func:`~shiny.ui.page_fillable` is used.
2. Otherwise, if `full_width` is `True`, :func:`~shiny.ui.page_fluid` is used.
3. If neither are `True`, :func:`~shiny.ui.page_fixed` is used.

Parameters
----------
Expand Down