Skip to content

Commit 51b1ef7

Browse files
committed
Server-side changes to support new HTML label/icon updates
1 parent 04f4d21 commit 51b1ef7

File tree

2 files changed

+54
-35
lines changed

2 files changed

+54
-35
lines changed

shiny/ui/_input_action_button.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,15 @@ def input_action_button(
6464
return tags.button(
6565
{"class": "btn btn-default action-button", "style": css(width=width)},
6666
icon,
67-
None if icon is None else " ",
67+
# The separator element helps us distinguish between the icon and label
68+
# when dynamically updating the button/link (see rstudio/shiny#4242)
69+
tags.span(class_="shiny-icon-separator") if icon else None,
70+
# Adds a space between the icon and label
71+
# TODO: this space gets removed when icon/label are updated dynamically,
72+
# which is not ideal. The 'right' way to do this would be to either
73+
# add a CSS class to the separator element, or wrap both the icon and
74+
# label in a container element.
75+
" " if icon and label else None,
6876
label,
6977
id=resolve_id(id),
7078
type="button",
@@ -117,6 +125,9 @@ def input_action_link(
117125
return tags.a(
118126
{"class": "action-button"},
119127
icon,
128+
# The separator element helps us distinguish between the icon and label
129+
# when dynamically updating the button/link (see rstudio/shiny#4242)
130+
tags.span(class_="shiny-icon-separator") if icon else None,
120131
label,
121132
id=resolve_id(id),
122133
href="#",

shiny/ui/_input_update.py

Lines changed: 42 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@
7171
def update_action_button(
7272
id: str,
7373
*,
74-
label: Optional[str] = None,
74+
label: Optional[TagChild] = None,
7575
icon: TagChild = None,
7676
disabled: Optional[bool] = None,
7777
session: Optional[Session] = None,
@@ -104,11 +104,9 @@ def update_action_button(
104104
"""
105105

106106
session = require_active_session(session)
107-
# TODO: supporting a TagChild for label would require changes to shiny.js
108-
# https://github.com/rstudio/shiny/issues/1140
109107
msg = {
110-
"label": label,
111-
"icon": session._process_ui(icon)["html"] if icon else None,
108+
"label": session._process_ui(label) if label else None,
109+
"icon": session._process_ui(icon) if icon else None,
112110
"disabled": disabled,
113111
}
114112
session.send_input_message(id, drop_none(msg))
@@ -119,7 +117,7 @@ def update_action_button(
119117
def update_action_link(
120118
id: str,
121119
*,
122-
label: Optional[str] = None,
120+
label: Optional[TagChild] = None,
123121
icon: TagChild = None,
124122
session: Optional[Session] = None,
125123
) -> None:
@@ -148,11 +146,9 @@ def update_action_link(
148146
"""
149147

150148
session = require_active_session(session)
151-
# TODO: supporting a TagChild for label would require changes to shiny.js
152-
# https://github.com/rstudio/shiny/issues/1140
153149
msg = {
154-
"label": label,
155-
"icon": session._process_ui(icon)["html"] if icon else None,
150+
"label": session._process_ui(label) if label else None,
151+
"icon": session._process_ui(icon) if icon else None,
156152
}
157153
session.send_input_message(id, drop_none(msg))
158154

@@ -229,7 +225,7 @@ def callback() -> None:
229225
def update_checkbox(
230226
id: str,
231227
*,
232-
label: Optional[str] = None,
228+
label: Optional[TagChild] = None,
233229
value: Optional[bool] = None,
234230
session: Optional[Session] = None,
235231
) -> None:
@@ -258,7 +254,10 @@ def update_checkbox(
258254
"""
259255

260256
session = require_active_session(session)
261-
msg = {"label": label, "value": value}
257+
msg = {
258+
"label": session._process_ui(label) if label else None,
259+
"value": value,
260+
}
262261
session.send_input_message(id, drop_none(msg))
263262

264263

@@ -267,7 +266,7 @@ def update_checkbox(
267266
def update_switch(
268267
id: str,
269268
*,
270-
label: Optional[str] = None,
269+
label: Optional[TagChild] = None,
271270
value: Optional[bool] = None,
272271
session: Optional[Session] = None,
273272
) -> None:
@@ -296,7 +295,10 @@ def update_switch(
296295
"""
297296

298297
session = require_active_session(session)
299-
msg = {"label": label, "value": value}
298+
msg = {
299+
"label": session._process_ui(label) if label else None,
300+
"value": value,
301+
}
300302
session.send_input_message(id, drop_none(msg))
301303

302304

@@ -305,7 +307,7 @@ def update_switch(
305307
def update_checkbox_group(
306308
id: str,
307309
*,
308-
label: Optional[str] = None,
310+
label: Optional[TagChild] = None,
309311
choices: Optional[ChoicesArg] = None,
310312
selected: Optional[str | list[str] | tuple[str, ...]] = None,
311313
inline: bool = False,
@@ -357,7 +359,7 @@ def update_checkbox_group(
357359
def update_radio_buttons(
358360
id: str,
359361
*,
360-
label: Optional[str] = None,
362+
label: Optional[TagChild] = None,
361363
choices: Optional[ChoicesArg] = None,
362364
selected: Optional[str] = None,
363365
inline: bool = False,
@@ -408,7 +410,7 @@ def _update_choice_input(
408410
id: str,
409411
*,
410412
type: Literal["checkbox", "radio"],
411-
label: Optional[str] = None,
413+
label: Optional[TagChild] = None,
412414
choices: Optional[ChoicesArg] = None,
413415
selected: Optional[str | list[str] | tuple[str, ...]] = None,
414416
inline: bool = False,
@@ -429,7 +431,11 @@ def _update_choice_input(
429431
inline=inline,
430432
)
431433
options = session._process_ui(opts)["html"]
432-
msg = {"label": label, "options": options, "value": selected}
434+
msg = {
435+
"label": session._process_ui(label) if label else None,
436+
"options": options,
437+
"value": selected,
438+
}
433439
session.send_input_message(id, drop_none(msg))
434440

435441

@@ -441,7 +447,7 @@ def _update_choice_input(
441447
def update_date(
442448
id: str,
443449
*,
444-
label: Optional[str] = None,
450+
label: Optional[TagChild] = None,
445451
value: Optional[date | str] = None,
446452
min: Optional[date | str] = None,
447453
max: Optional[date | str] = None,
@@ -478,7 +484,7 @@ def update_date(
478484

479485
session = require_active_session(session)
480486
msg = {
481-
"label": label,
487+
"label": session._process_ui(label) if label else None,
482488
"value": _as_date_attr(value),
483489
"min": _as_date_attr(min),
484490
"max": _as_date_attr(max),
@@ -491,7 +497,7 @@ def update_date(
491497
def update_date_range(
492498
id: str,
493499
*,
494-
label: Optional[str] = None,
500+
label: Optional[TagChild] = None,
495501
start: Optional[date | str] = None,
496502
end: Optional[date | str] = None,
497503
min: Optional[date | str] = None,
@@ -535,7 +541,7 @@ def update_date_range(
535541
session = require_active_session(session)
536542
value = {"start": _as_date_attr(start), "end": _as_date_attr(end)}
537543
msg = {
538-
"label": label,
544+
"label": session._process_ui(label) if label else None,
539545
"value": drop_none(value),
540546
"min": _as_date_attr(min),
541547
"max": _as_date_attr(max),
@@ -551,7 +557,7 @@ def update_date_range(
551557
def update_numeric(
552558
id: str,
553559
*,
554-
label: Optional[str] = None,
560+
label: Optional[TagChild] = None,
555561
value: Optional[float] = None,
556562
min: Optional[float] = None,
557563
max: Optional[float] = None,
@@ -589,7 +595,7 @@ def update_numeric(
589595

590596
session = require_active_session(session)
591597
msg = {
592-
"label": label,
598+
"label": session._process_ui(label) if label else None,
593599
"value": value,
594600
"min": min,
595601
"max": max,
@@ -606,7 +612,7 @@ def update_numeric(
606612
def update_select(
607613
id: str,
608614
*,
609-
label: Optional[str] = None,
615+
label: Optional[TagChild] = None,
610616
choices: Optional[SelectChoicesArg] = None,
611617
selected: Optional[str | list[str]] = None,
612618
session: Optional[Session] = None,
@@ -652,12 +658,10 @@ def update_select(
652658
options = None
653659
else:
654660
option_tags = _render_choices(_normalize_choices(choices), selected)
655-
# Typing problem due to a bug in pylance:
656-
# https://github.com/microsoft/pylance-release/issues/2377
657-
options = session._process_ui(option_tags)["html"] # type: ignore
661+
options = session._process_ui(option_tags)["html"]
658662

659663
msg = {
660-
"label": label,
664+
"label": session._process_ui(label) if label else None,
661665
"options": options,
662666
"value": selected_values,
663667
}
@@ -675,7 +679,7 @@ class FlatSelectChoice(TypedDict):
675679
def update_selectize(
676680
id: str,
677681
*,
678-
label: Optional[str] = None,
682+
label: Optional[TagChild] = None,
679683
choices: Optional[SelectChoicesArg] = None,
680684
selected: Optional[str | list[str]] = None,
681685
options: Optional[dict[str, str | float | JSEval]] = None,
@@ -854,7 +858,7 @@ def selectize_choices_json(request: Request) -> Response:
854858
def update_slider(
855859
id: str,
856860
*,
857-
label: Optional[str] = None,
861+
label: Optional[TagChild] = None,
858862
value: Optional[SliderValueArg | tuple[SliderValueArg, SliderValueArg]] = None,
859863
min: Optional[SliderValueArg] = None,
860864
max: Optional[SliderValueArg] = None,
@@ -928,7 +932,7 @@ def update_slider(
928932
value_num = None
929933

930934
msg = {
931-
"label": label,
935+
"label": session._process_ui(label) if label else None,
932936
"value": value_num,
933937
"min": min_num,
934938
"max": max_num,
@@ -948,7 +952,7 @@ def update_slider(
948952
def update_text(
949953
id: str,
950954
*,
951-
label: Optional[str] = None,
955+
label: Optional[TagChild] = None,
952956
value: Optional[str] = None,
953957
placeholder: Optional[str] = None,
954958
session: Optional[Session] = None,
@@ -980,7 +984,11 @@ def update_text(
980984
"""
981985

982986
session = require_active_session(session)
983-
msg = {"label": label, "value": value, "placeholder": placeholder}
987+
msg = {
988+
"label": session._process_ui(label) if label else None,
989+
"value": value,
990+
"placeholder": placeholder,
991+
}
984992
session.send_input_message(id, drop_none(msg))
985993

986994

0 commit comments

Comments
 (0)