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

Smarter, lazier, and more complete page default/api for express #893

Merged
merged 31 commits into from
Dec 22, 2023

Conversation

cpsievert
Copy link
Collaborator

@cpsievert cpsievert commented Dec 11, 2023

This PR currently just introduces a TopLevelRecallContextManager(), which inspects it's args to determine a smarter page (i.e., page_sidebar()/page_navbar()/something else) based on the presence of top-level layout.sidebar()/layout.nav()/other components.

This new approach isn't compatible with the more immediate/imperative layout.set_page(layout.page_*()) API, so I'm removing it for now. This does bring up, however, more questions as to how to the page API (#866) should look. Originally I was thinking .set_page_*() + .set_title() would be sensible, but on second thought, a set_page_preferences() is probably more ideal. There you could not only control page kwargs (e.g., title, lang, etc), but also parameters related to default page container decision (e.g., fillable, wider (i.e., page_fluid() vs page_fixed()), etc))

Also note that, we still currently have the issue of layout.sidebar() in a non-top-level context. I think, ideally, a non-top-level RecallContextManager could handle this by doing essentially the same as TopLevelRecallContextManager (i.e., wrapping any Sidebar(s) into a layout_sidebar())

@wch
Copy link
Collaborator

wch commented Dec 11, 2023

Things the user needs to control:

  • Title
  • Fillable
  • Width
  • (Maybe) If inference is wrong, explicit way of setting page function

Possible interface for this:

  • set_page_xxx()
  • set_title(), set_fillable(), set_restrict_width()
  • set_page_preferences(*, title, fillable, width, **kwargs)

@wch
Copy link
Collaborator

wch commented Dec 16, 2023

I've added the following functions:

set_page_title()
set_page_lang()

# The two below affect heuristics for which page function is used.
set_page_fillable()
set_page_wider()

If the user wants to explicitly choose which page function is used, there are the following:

use_page_fixed()
use_page_fluid()
use_page_fillable()
use_page_sidebar()
use_page_navbar()

All of these functions live in express._page, but I haven't imported them into express.layout, because that will introduce merge conflicts with #904. I think we should merge these two PRs and then export the functions here from express.ui.

Comment on lines 58 to 61
if _fillable:
_page_fn = (
ui.page_fillable
) # pyright: ignore[reportGeneralTypeIssues]
Copy link
Collaborator Author

@cpsievert cpsievert Dec 18, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not that we absolutely need this now, but I think we could support wider=F when fillable=T by including a {"class": "container"} (probably on the <body>)?

shiny/express/_page.py Outdated Show resolved Hide resolved
shiny/express/_page.py Outdated Show resolved Hide resolved
@schloerke schloerke added this to the v0.7.0 milestone Dec 18, 2023
@wch
Copy link
Collaborator

wch commented Dec 18, 2023

From a conversation with @cpsievert, @gadenbuie, @jcheng5:

Things we can do now:

  • Add page_opts() function. Make all args keyword only (first arg is *).

  • Make page_auto() the default page. Also add that function to core UI.

  • Add set_page_fn()

    layout.set_page_fn(
        lambda *args: ui.page_navbar(*args, ...)
    )
    
    # or
    
    def my_page_fn(*args):
        return ui.page_navbar(*args, ...)
    
    layout.set_page_fn(my_page_fn)

Things we can do possibly in the future:

  • Maybe add page_opts(mode = "navbar", ...) or page_opts_navbar(...)
  • Allow passing *kwargs to page_opts()? How to distinguish between HTML attributes and proper args?

@schloerke schloerke modified the milestones: v0.6.1, v0.7.0 Dec 19, 2023
@wch wch changed the base branch from main to express-layout-to-ui December 21, 2023 06:07
@wch
Copy link
Collaborator

wch commented Dec 21, 2023

I've retargeted this PR against express-layout-to-ui (#904) to make the changes make more sense.

I implemented the changes as described in the previous comment:

  • Add page_opts() function. Make all args keyword only (first arg is *).

  • Make page_auto() the default page. Also add that function to core UI.

  • However, for the third item, I made a change. Instead of adding a function set_page_fn(), I added a page_fn parameter to page_opts(). It would be used like this:

    page_opts(page_fn=shiny.ui.page_fillable)

    I did this because the parameters to page_opts() basically map to page_auto() parameters, and page_auto() already accepts _page_fn.

The page function to use. If ``None`` (the default), will automatically choose
one based on the arguments provided.
_fillable
This has an effect only if there are no sidebars or top-level navs. If ``True``,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

page_navbar and page_sidebar both take a fillable argument, we could pass it through

``False`` (the default), the value of ``_full_width`` will determine which page
function is used.
_full_width
This has an effect only if there are no sidebars or top-level navs, and
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not as part of this PR, but we should support narrow layouts with sidebars or top-level navs.

_page_fn: Callable[..., Tag] | None = None,
_fillable: bool = False,
_full_width: bool = False,
**kwargs: object,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove underscore prefixes, and make the **kwargs a dictionary argument instead

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or don't take _page_fn

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I considered taking out page_fn, but I think we should keep it because it's useful when, in Express, you call page_opts(page_fn=...). The page_opts function can just pass it through to this function.

Base automatically changed from express-layout-to-ui to main December 21, 2023 19:24
@wch wch marked this pull request as ready for review December 22, 2023 00:00
@wch wch merged commit 22b1db3 into main Dec 22, 2023
26 checks passed
@wch wch deleted the express-inspect-args branch December 22, 2023 00:17
schloerke added a commit that referenced this pull request Jan 8, 2024
* main: (24 commits)
  Use dynamic version of py-shiny for deploy tests (#970)
  Add underscores to hide some imports (#978)
  Add rsconnect json files(shinyapps.io tests) and folium tests (#928)
  Express' `value_box()` no longer includes named positional args (#966)
  Include `tooltip()` and `popover()` in express (#949)
  Remove extra call to run_express()
  Call `tagify()` early to intercept `AttributeErrors` (#941)
  Don't pass sidebar twice to navbar_page
  Update changelog
  Update changelog
  Switch from `requests` to `urllib` (#940)
  Bump version to 0.6.1.1
  Fix docstring for page_opts
  Fix API doc sections for Express
  Smarter, lazier, and more complete page default/api for express (#893)
  Change `express.layout` to `express.ui` (#904)
  Remove `@output` from examples (#790)
  feat: Allow for `App` `server=` to take `input` only (#920)
  Add fixes for type stub generation (#828)
  Move quarto express docs to bottom
  ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Shiny express, placing UI elements above the sidebar context manager causes error.
4 participants