Skip to content
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
14 changes: 10 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,26 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### New features

### Improvements
* `ui.sidebar()` is now interactively resizable. (#2020)

* `selectize`, `remove_button`, and `options` parameters of `ui.input_select()` have been deprecated; use `ui.input_selectize()` instead. (Thanks, @ErdaradunGaztea!) (#1947)
* `ui.update_*()` functions now accept `ui.TagChild` (i.e., HTML) as input to the `label` and `icon` arguments. (#2020)

* `playwright.controller.InputActionButton` gains a `expect_icon()` method. As a result, the already existing `expect_label()` no longer includes the icon. (#2020)

### Improvements

* Improved the styling and readability of markdown tables rendered by `ui.Chat()` and `ui.MarkdownStream()`. (#1973)

* `selectize`, `remove_button`, and `options` parameters of `ui.input_select()` have been deprecated; use `ui.input_selectize()` instead. (Thanks, @ErdaradunGaztea!) (#1947)

### Bug fixes

* Fixed an issue with `ui.Chat()` sometimes wanting to scroll a parent element. (#1996)

* Explicitly call out module usage in UI input bookmark button documentation. (#1983)

* Fix missing session when trying to display an error duing bookmarking. (#1984)

* Fixed an issue with `ui.Chat()` sometimes wanting to scroll a parent element. (#1996)


## [1.4.0] - 2025-04-08

Expand Down
2 changes: 1 addition & 1 deletion shiny/_versions.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
shiny_html_deps = "1.10.0.9001"
shiny_html_deps = "1.11.1.9000"
bslib = "0.9.0.9000"
htmltools = "0.5.8.9000"
bootstrap = "5.3.1"
Expand Down
25 changes: 22 additions & 3 deletions shiny/playwright/controller/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -451,8 +451,6 @@ def expect_label(
"""
Expect the label of the input button to have a specific value.

Note: This must include the icon if it is present!

Parameters
----------
value
Expand All @@ -461,7 +459,28 @@ def expect_label(
The maximum time to wait for the expectation to be fulfilled. Defaults to `None`.
"""

self.expect.to_have_text(value, timeout=timeout)
loc_label = self.loc.locator(".action-label")
playwright_expect(loc_label).to_have_text(value, timeout=timeout)

def expect_icon(
self,
value: PatternOrStr,
*,
timeout: Timeout = None,
) -> None:
"""
Expect the icon of the input button to have a specific value.

Parameters
----------
value
The expected value of the icon.
timeout
The maximum time to wait for the expectation to be fulfilled. Defaults to `None`.
"""

loc_icon = self.loc.locator(".action-icon")
playwright_expect(loc_icon).to_have_text(value, timeout=timeout)

def click(self, *, timeout: Timeout = None, **kwargs: object) -> None:
"""
Expand Down
15 changes: 13 additions & 2 deletions shiny/ui/_input_action_button.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,15 @@ def input_action_button(
if "_add_ws" not in kwargs:
kwargs["_add_ws"] = True

if icon is not None:
icon = tags.span(icon, class_="action-icon")

if label is not None:
label = tags.span(label, class_="action-label")

return tags.button(
{"class": "btn btn-default action-button", "style": css(width=width)},
icon,
None if icon is None else " ",
label,
id=resolve_id(id),
type="button",
Expand Down Expand Up @@ -114,8 +119,14 @@ def input_action_link(
* :func:`~shiny.reactive.event`
"""

if icon is not None:
icon = tags.span(icon, class_="action-icon")

if label is not None:
label = tags.span(label, class_="action-label")

return tags.a(
{"class": "action-button"},
{"class": "action-button action-link"},
icon,
label,
id=resolve_id(id),
Expand Down
76 changes: 42 additions & 34 deletions shiny/ui/_input_update.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@
def update_action_button(
id: str,
*,
label: Optional[str] = None,
label: Optional[TagChild] = None,
icon: TagChild = None,
disabled: Optional[bool] = None,
session: Optional[Session] = None,
Expand Down Expand Up @@ -104,11 +104,9 @@ def update_action_button(
"""

session = require_active_session(session)
# TODO: supporting a TagChild for label would require changes to shiny.js
# https://github.com/rstudio/shiny/issues/1140
msg = {
"label": label,
"icon": session._process_ui(icon)["html"] if icon else None,
"label": session._process_ui(label) if label is not None else None,
"icon": session._process_ui(icon) if icon is not None else None,
"disabled": disabled,
}
session.send_input_message(id, drop_none(msg))
Expand All @@ -119,7 +117,7 @@ def update_action_button(
def update_action_link(
id: str,
*,
label: Optional[str] = None,
label: Optional[TagChild] = None,
icon: TagChild = None,
session: Optional[Session] = None,
) -> None:
Expand Down Expand Up @@ -148,11 +146,9 @@ def update_action_link(
"""

session = require_active_session(session)
# TODO: supporting a TagChild for label would require changes to shiny.js
# https://github.com/rstudio/shiny/issues/1140
msg = {
"label": label,
"icon": session._process_ui(icon)["html"] if icon else None,
"label": session._process_ui(label) if label is not None else None,
"icon": session._process_ui(icon) if icon is not None else None,
}
session.send_input_message(id, drop_none(msg))

Expand Down Expand Up @@ -229,7 +225,7 @@ def callback() -> None:
def update_checkbox(
id: str,
*,
label: Optional[str] = None,
label: Optional[TagChild] = None,
value: Optional[bool] = None,
session: Optional[Session] = None,
) -> None:
Expand Down Expand Up @@ -258,7 +254,10 @@ def update_checkbox(
"""

session = require_active_session(session)
msg = {"label": label, "value": value}
msg = {
"label": session._process_ui(label) if label is not None else None,
"value": value,
}
session.send_input_message(id, drop_none(msg))


Expand All @@ -267,7 +266,7 @@ def update_checkbox(
def update_switch(
id: str,
*,
label: Optional[str] = None,
label: Optional[TagChild] = None,
value: Optional[bool] = None,
session: Optional[Session] = None,
) -> None:
Expand Down Expand Up @@ -296,7 +295,10 @@ def update_switch(
"""

session = require_active_session(session)
msg = {"label": label, "value": value}
msg = {
"label": session._process_ui(label) if label is not None else None,
"value": value,
}
session.send_input_message(id, drop_none(msg))


Expand All @@ -305,7 +307,7 @@ def update_switch(
def update_checkbox_group(
id: str,
*,
label: Optional[str] = None,
label: Optional[TagChild] = None,
choices: Optional[ChoicesArg] = None,
selected: Optional[str | list[str] | tuple[str, ...]] = None,
inline: bool = False,
Expand Down Expand Up @@ -357,7 +359,7 @@ def update_checkbox_group(
def update_radio_buttons(
id: str,
*,
label: Optional[str] = None,
label: Optional[TagChild] = None,
choices: Optional[ChoicesArg] = None,
selected: Optional[str] = None,
inline: bool = False,
Expand Down Expand Up @@ -408,7 +410,7 @@ def _update_choice_input(
id: str,
*,
type: Literal["checkbox", "radio"],
label: Optional[str] = None,
label: Optional[TagChild] = None,
choices: Optional[ChoicesArg] = None,
selected: Optional[str | list[str] | tuple[str, ...]] = None,
inline: bool = False,
Expand All @@ -429,7 +431,11 @@ def _update_choice_input(
inline=inline,
)
options = session._process_ui(opts)["html"]
msg = {"label": label, "options": options, "value": selected}
msg = {
"label": session._process_ui(label) if label is not None else None,
"options": options,
"value": selected,
}
session.send_input_message(id, drop_none(msg))


Expand All @@ -441,7 +447,7 @@ def _update_choice_input(
def update_date(
id: str,
*,
label: Optional[str] = None,
label: Optional[TagChild] = None,
value: Optional[date | str] = None,
min: Optional[date | str] = None,
max: Optional[date | str] = None,
Expand Down Expand Up @@ -478,7 +484,7 @@ def update_date(

session = require_active_session(session)
msg = {
"label": label,
"label": session._process_ui(label) if label is not None else None,
"value": _as_date_attr(value),
"min": _as_date_attr(min),
"max": _as_date_attr(max),
Expand All @@ -491,7 +497,7 @@ def update_date(
def update_date_range(
id: str,
*,
label: Optional[str] = None,
label: Optional[TagChild] = None,
start: Optional[date | str] = None,
end: Optional[date | str] = None,
min: Optional[date | str] = None,
Expand Down Expand Up @@ -535,7 +541,7 @@ def update_date_range(
session = require_active_session(session)
value = {"start": _as_date_attr(start), "end": _as_date_attr(end)}
msg = {
"label": label,
"label": session._process_ui(label) if label is not None else None,
"value": drop_none(value),
"min": _as_date_attr(min),
"max": _as_date_attr(max),
Expand All @@ -551,7 +557,7 @@ def update_date_range(
def update_numeric(
id: str,
*,
label: Optional[str] = None,
label: Optional[TagChild] = None,
value: Optional[float] = None,
min: Optional[float] = None,
max: Optional[float] = None,
Expand Down Expand Up @@ -589,7 +595,7 @@ def update_numeric(

session = require_active_session(session)
msg = {
"label": label,
"label": session._process_ui(label) if label is not None else None,
"value": value,
"min": min,
"max": max,
Expand All @@ -606,7 +612,7 @@ def update_numeric(
def update_select(
id: str,
*,
label: Optional[str] = None,
label: Optional[TagChild] = None,
choices: Optional[SelectChoicesArg] = None,
selected: Optional[str | list[str]] = None,
session: Optional[Session] = None,
Expand Down Expand Up @@ -652,12 +658,10 @@ def update_select(
options = None
else:
option_tags = _render_choices(_normalize_choices(choices), selected)
# Typing problem due to a bug in pylance:
# https://github.com/microsoft/pylance-release/issues/2377
options = session._process_ui(option_tags)["html"] # type: ignore
options = session._process_ui(option_tags)["html"]

msg = {
"label": label,
"label": session._process_ui(label) if label is not None else None,
"options": options,
"value": selected_values,
}
Expand All @@ -675,7 +679,7 @@ class FlatSelectChoice(TypedDict):
def update_selectize(
id: str,
*,
label: Optional[str] = None,
label: Optional[TagChild] = None,
choices: Optional[SelectChoicesArg] = None,
selected: Optional[str | list[str]] = None,
options: Optional[dict[str, str | float | JSEval]] = None,
Expand Down Expand Up @@ -854,7 +858,7 @@ def selectize_choices_json(request: Request) -> Response:
def update_slider(
id: str,
*,
label: Optional[str] = None,
label: Optional[TagChild] = None,
value: Optional[SliderValueArg | tuple[SliderValueArg, SliderValueArg]] = None,
min: Optional[SliderValueArg] = None,
max: Optional[SliderValueArg] = None,
Expand Down Expand Up @@ -928,7 +932,7 @@ def update_slider(
value_num = None

msg = {
"label": label,
"label": session._process_ui(label) if label is not None else None,
"value": value_num,
"min": min_num,
"max": max_num,
Expand All @@ -948,7 +952,7 @@ def update_slider(
def update_text(
id: str,
*,
label: Optional[str] = None,
label: Optional[TagChild] = None,
value: Optional[str] = None,
placeholder: Optional[str] = None,
session: Optional[Session] = None,
Expand Down Expand Up @@ -980,7 +984,11 @@ def update_text(
"""

session = require_active_session(session)
msg = {"label": label, "value": value, "placeholder": placeholder}
msg = {
"label": session._process_ui(label) if label is not None else None,
"value": value,
"placeholder": placeholder,
}
session.send_input_message(id, drop_none(msg))


Expand Down
2 changes: 1 addition & 1 deletion shiny/www/shared/_version.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"note!": "Generated by scripts/htmlDependencies.R: do not edit by hand",
"package": "shiny",
"version": "1.10.0.9001 (rstudio/shiny@ca41c0831befcf8feea17980a91983ce21d1b8a2)"
"version": "1.11.1.9000 (rstudio/shiny@ecf6bfe9a7696695c67c90fbf5901986a61c024c)"
}
4 changes: 2 additions & 2 deletions shiny/www/shared/bootstrap/_version.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"note!": "Generated by scripts/htmlDependencies.R: do not edit by hand",
"shiny_version": "1.10.0.9001 (rstudio/shiny@ca41c0831befcf8feea17980a91983ce21d1b8a2)",
"bslib_version": "0.9.0.9000 (rstudio/bslib@7cf80506c6beb9d7e5f2f146d2c9c935bbaf1635)",
"shiny_version": "1.11.1.9000 (rstudio/shiny@ecf6bfe9a7696695c67c90fbf5901986a61c024c)",
"bslib_version": "0.9.0.9000 (rstudio/bslib@9562108e40a0bffb4a7c8709c2963509435c5c0f)",
"htmltools_version": "0.5.8.9000 (rstudio/htmltools@487aa0bed7313d7597b6edd5810e53cab0061198)",
"bootstrap_version": "5.3.1"
}
2 changes: 1 addition & 1 deletion shiny/www/shared/bootstrap/bootstrap.min.css

Large diffs are not rendered by default.

Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
2 changes: 1 addition & 1 deletion shiny/www/shared/bslib/_version.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"note!": "Generated by scripts/htmlDependencies.R: do not edit by hand",
"package": "bslib",
"version": "0.9.0.9000 (rstudio/bslib@7cf80506c6beb9d7e5f2f146d2c9c935bbaf1635)"
"version": "0.9.0.9000 (rstudio/bslib@9562108e40a0bffb4a7c8709c2963509435c5c0f)"
}
2 changes: 1 addition & 1 deletion shiny/www/shared/bslib/components/components.css

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions shiny/www/shared/bslib/components/components.min.js

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions shiny/www/shared/bslib/components/components.min.js.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion shiny/www/shared/busy-indicators/busy-indicators.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading