Skip to content

Commit ae49e4c

Browse files
fix: Introduce a more ergonomic API for express.ui.insert_accordion_panel() (#2042)
Co-authored-by: Karan Gathani <[email protected]> Co-authored-by: Karan <[email protected]>
1 parent 6bebea5 commit ae49e4c

File tree

9 files changed

+375
-219
lines changed

9 files changed

+375
-219
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2121

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

24+
### Changes
25+
26+
* `express.ui.insert_accordion_panel()`'s function signature has changed to be more ergonomic. Now you can pass the `panel_title` and `panel_contents` directly instead of `ui.hold()`ing the `ui.accordion_panel()` context manager. (#2042)
27+
2428
### Improvements
2529

2630
* Improved the styling and readability of markdown tables rendered by `ui.Chat()` and `ui.MarkdownStream()`. (#1973)
Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,21 @@
11
import random
22

3-
from shiny import reactive, ui
4-
from shiny.express import input
5-
6-
7-
def make_panel(letter):
8-
return ui.accordion_panel(
9-
f"Section {letter}", f"Some narrative for section {letter}"
10-
)
11-
3+
from shiny import reactive
4+
from shiny.express import input, ui
125

136
ui.input_action_button("add_panel", "Add random panel", class_="mt-3 mb-3")
14-
ui.accordion(*[make_panel(letter) for letter in "ABCDE"], id="acc", multiple=True)
7+
8+
with ui.accordion(id="acc", multiple=True):
9+
for letter in "ABCDE":
10+
with ui.accordion_panel(f"Section {letter}"):
11+
f"Some narrative for section {letter}"
1512

1613

1714
@reactive.effect
1815
@reactive.event(input.add_panel)
1916
def _():
20-
ui.insert_accordion_panel("acc", make_panel(str(random.randint(0, 10000))))
17+
ui.insert_accordion_panel(
18+
"acc",
19+
f"Section {random.randint(0, 10000)}",
20+
f"Some narrative for section {random.randint(0, 10000)}",
21+
)

shiny/express/ui/__init__.py

Lines changed: 52 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,12 @@
11
from __future__ import annotations
22

3-
43
from htmltools import (
5-
TagList,
4+
HTML,
65
Tag,
7-
TagChild,
86
TagAttrs,
97
TagAttrValue,
10-
tags,
11-
HTML,
12-
head_content,
8+
TagChild,
9+
TagList,
1310
a,
1411
br,
1512
code,
@@ -21,116 +18,113 @@
2118
h4,
2219
h5,
2320
h6,
21+
head_content,
2422
hr,
2523
img,
2624
p,
2725
pre,
2826
span,
2927
strong,
30-
)
31-
32-
from ...ui import (
33-
fill,
34-
)
35-
36-
from ...ui import (
37-
busy_indicators,
28+
tags,
3829
)
3930

4031
from ...ui import (
4132
AccordionPanel,
4233
AnimationOptions,
4334
CardItem,
35+
Progress,
4436
ShowcaseLayout,
4537
Sidebar,
4638
SliderStepArg,
4739
SliderValueArg,
40+
Theme,
4841
ValueBoxTheme,
42+
bind_task_button,
4943
brush_opts,
44+
busy_indicators,
5045
click_opts,
5146
dblclick_opts,
47+
fill,
5248
help_text,
5349
hover_opts,
5450
include_css,
5551
include_js,
56-
input_bookmark_button,
5752
input_action_button,
5853
input_action_link,
54+
input_bookmark_button,
5955
input_checkbox,
6056
input_checkbox_group,
61-
input_switch,
62-
input_radio_buttons,
6357
input_dark_mode,
6458
input_date,
6559
input_date_range,
6660
input_file,
6761
input_numeric,
6862
input_password,
63+
input_radio_buttons,
6964
input_select,
7065
input_selectize,
7166
input_slider,
72-
bind_task_button,
67+
input_switch,
7368
input_task_button,
7469
input_text,
7570
input_text_area,
71+
insert_ui,
72+
js_eval,
73+
markdown,
74+
modal,
75+
modal_button,
76+
modal_remove,
77+
modal_show,
78+
nav_spacer,
79+
navbar_options,
80+
notification_remove,
81+
notification_show,
7682
panel_title,
77-
insert_accordion_panel,
7883
remove_accordion_panel,
84+
remove_nav_panel,
85+
remove_ui,
7986
update_accordion,
8087
update_accordion_panel,
81-
update_sidebar,
8288
update_action_button,
8389
update_action_link,
8490
update_checkbox,
85-
update_switch,
8691
update_checkbox_group,
87-
update_radio_buttons,
8892
update_dark_mode,
8993
update_date,
9094
update_date_range,
95+
update_nav_panel,
96+
update_navs,
9197
update_numeric,
98+
update_popover,
99+
update_radio_buttons,
92100
update_select,
93101
update_selectize,
102+
update_sidebar,
94103
update_slider,
104+
update_switch,
95105
update_task_button,
96106
update_text,
97107
update_text_area,
98-
update_navs,
99108
update_tooltip,
100-
update_popover,
101-
insert_ui,
102-
remove_ui,
103-
markdown,
104-
modal_button,
105-
modal,
106-
modal_show,
107-
modal_remove,
108-
notification_show,
109-
notification_remove,
110-
nav_spacer,
111-
navbar_options,
112-
remove_nav_panel,
113-
update_nav_panel,
114-
Progress,
115-
Theme,
116109
value_box_theme,
117-
js_eval,
118110
)
119-
111+
from ...ui._chat import ChatExpress as Chat
112+
from ...ui._markdown_stream import (
113+
ExpressMarkdownStream as MarkdownStream,
114+
)
120115
from ._cm_components import (
121-
sidebar,
122-
layout_sidebar,
123-
layout_column_wrap,
124-
layout_columns,
116+
accordion,
117+
accordion_panel,
125118
card,
126119
card_body,
127-
card_header,
128120
card_footer,
129-
accordion,
130-
accordion_panel,
131-
nav_panel,
121+
card_header,
122+
layout_column_wrap,
123+
layout_columns,
124+
layout_sidebar,
132125
nav_control,
133126
nav_menu,
127+
nav_panel,
134128
navset_bar,
135129
navset_card_pill,
136130
navset_card_tab,
@@ -140,32 +134,25 @@
140134
navset_pill_list,
141135
navset_tab,
142136
navset_underline,
143-
value_box,
144-
panel_well,
137+
panel_absolute,
145138
panel_conditional,
146139
panel_fixed,
147-
panel_absolute,
148-
tooltip,
140+
panel_well,
149141
popover,
142+
sidebar,
143+
tooltip,
144+
value_box,
150145
)
151-
152-
from ...ui._chat import ChatExpress as Chat
153-
154-
from ...ui._markdown_stream import (
155-
ExpressMarkdownStream as MarkdownStream,
156-
)
157-
158-
from ._page import (
159-
page_opts,
160-
)
161-
162146
from ._hold import (
163147
hold,
164148
)
165-
166149
from ._insert import (
150+
insert_accordion_panel,
167151
insert_nav_panel,
168152
)
153+
from ._page import (
154+
page_opts,
155+
)
169156

170157
__all__ = (
171158
# Imports from htmltools

shiny/express/ui/_insert.py

Lines changed: 72 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,82 @@
77
@ui.hold() pass the UI as a value without displaying it.
88
"""
99

10-
from typing import Literal, Optional
10+
from typing import Literal, Optional, Union
1111

12-
from htmltools import TagChild
12+
from htmltools import TagAttrs, TagChild
1313

1414
from ..._docstring import add_example
1515
from ...session import Session
16+
from ...types import MISSING, MISSING_TYPE
17+
18+
19+
@add_example()
20+
def insert_accordion_panel(
21+
id: str,
22+
panel_title: str,
23+
*panel_contents: Union[TagChild, TagAttrs],
24+
panel_value: Union[str, MISSING_TYPE, None] = MISSING,
25+
panel_icon: TagChild = None,
26+
target: Optional[str] = None,
27+
position: Literal["after", "before"] = "after",
28+
session: Optional[Session] = None,
29+
) -> None:
30+
"""
31+
Insert an accordion panel into an existing accordion.
32+
33+
Parameters
34+
----------
35+
id
36+
A string that matches an existing :func:`~shiny.ui.express.accordion`'s `id`.
37+
panel_title
38+
The title to appear in the panel header.
39+
panel_contents
40+
UI elements for the panel's body. Can also be a dict of tag attributes for the
41+
body's HTML container.
42+
panel_value
43+
A character string that uniquely identifies this panel. If `MISSING`, the
44+
`title` will be used.
45+
panel_icon
46+
A :class:`~htmltools.TagChild` which is positioned just before the `title`.
47+
target
48+
The `value` of an existing panel to insert next to.
49+
position
50+
Should `panel` be added before or after the target? When `target=None`,
51+
`"after"` will append after the last panel and `"before"` will prepend before
52+
the first panel.
53+
session
54+
A Shiny session object (the default should almost always be used).
55+
56+
References
57+
----------
58+
[Bootstrap Accordion](https://getbootstrap.com/docs/5.3/components/accordion/)
59+
60+
See Also
61+
--------
62+
* :func:`~shiny.ui.express.accordion`
63+
* :func:`~shiny.ui.express.accordion_panel`
64+
* :func:`~shiny.ui.express.update_accordion`
65+
"""
66+
67+
from ...ui import AccordionPanel, accordion_panel, insert_accordion_panel
68+
69+
if isinstance(panel_title, AccordionPanel):
70+
# If the user passed an AccordionPanel, we can just use it as is.
71+
# This isn't recommended, but we support it for backwards compatibility
72+
# with the old API.
73+
panel = panel_title
74+
else:
75+
panel = accordion_panel(
76+
panel_title, *panel_contents, value=panel_value, icon=panel_icon
77+
)
78+
79+
insert_accordion_panel(
80+
id=id,
81+
panel=panel,
82+
target=target,
83+
position=position,
84+
session=session,
85+
)
1686

1787

1888
@add_example()

shiny/ui/_accordion.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -315,17 +315,17 @@ def accordion_panel(
315315
Parameters
316316
----------
317317
title
318-
A title to appear in the :func:`~shiny.ui.accordion_panel`'s header.
318+
A title to appear in the panel's header.
319319
*args
320-
Contents to the accordion panel body. Or tag attributes that are supplied to the
321-
returned :class:`~htmltools.Tag` object.
320+
UI elements for the panel's body. Can also be a dict of tag attributes for the
321+
body's HTML container.
322322
value
323323
A character string that uniquely identifies this panel. If `MISSING`, the
324324
`title` will be used.
325325
icon
326-
A :class:`~htmltools.Tag` which is positioned just before the `title`.
326+
A :class:`~htmltools.TagChild` which is positioned just before the `title`.
327327
**kwargs
328-
Tag attributes to the `accordion-body` div Tag.
328+
Tag attributes for the body's HTML container.
329329
330330
Returns
331331
-------

0 commit comments

Comments
 (0)