-
Notifications
You must be signed in to change notification settings - Fork 108
Closed
Labels
Description
Problem
I can see two issues with how shiny.express.ui
handles positional arguments:
- Many functions don't pass along positional arguments (i.e., they have
*
instead of*args
in their signature). This means you can't currently use things likeui.card()
the "functional" way:
from shiny.express import ui
ui.card("foo", "bar")
TypeError: card() takes 0 positional arguments but 2 were given
- Some functions have named positional arguments, which forces those arguments to be specified when used the "context-manager" way. For example, since
value_box()
hastitle
/value
as named positional args, usage must look like this:
with value_box("Title", "Value"):
pass
...which is unfortunate, especially when you want to a dynamically rendered value.
Proposal
I think we can solve both issues by taking inspiration from how card_header()
currently works. That is, if the underlying UI function takes any positional arguments, we always start the express function with *args
and pass those args to the underlying UI function
py-shiny/shiny/express/ui/_cm_components.py
Lines 455 to 487 in b61452d
def card_header( | |
*args: TagChild | TagAttrs, | |
container: TagFunction = ui.tags.div, | |
**kwargs: TagAttrValue, | |
) -> RecallContextManager[CardItem]: | |
""" | |
Context manager for a card header container | |
This function wraps :func:`~shiny.ui.card_header`. | |
A general container for the "header" of a :func:`~shiny.ui.card`. This component is designed | |
to be provided as a direct child to :func:`~shiny.ui.card`. | |
The header has a different background color and border than the rest of the card. | |
Parameters | |
---------- | |
*args | |
Contents to the header container. Or tag attributes that are supplied to the | |
resolved :class:`~htmltools.Tag` object. | |
container | |
Method for the returned Tag object. Defaults to :func:`~shiny.ui.tags.div`. | |
**kwargs | |
Additional HTML attributes for the returned Tag. | |
""" | |
return RecallContextManager( | |
ui.card_header, | |
args=args, | |
kwargs=dict( | |
container=container, | |
**kwargs, | |
), | |
) |
This does lead to the question of whether functions like nav_panel()
should be (title, *args, **kwargs)
or (*args, **kwargs)
, but it seems pretty sensible to me (for consistency sake) that we go in the latter direction.