99from .._utils import drop_none , private_random_id
1010from ..bookmark import restore_input
1111from ..session import require_active_session
12- from ..types import MISSING , MISSING_TYPE
12+ from ..types import MISSING , MISSING_TYPE , ListOrTuple
1313from ._html_deps_shinyverse import components_dependencies
1414from ._tag import consolidate_attrs
1515from .css ._css_unit import CssUnit , as_css_unit
@@ -176,7 +176,7 @@ def tagify(self) -> Tag:
176176def accordion (
177177 * args : AccordionPanel | TagAttrs ,
178178 id : Optional [str ] = None ,
179- open : Optional [bool | str | list [str ]] = None ,
179+ open : Optional [bool | str | ListOrTuple [str ]] = None ,
180180 multiple : bool = True ,
181181 class_ : Optional [str ] = None ,
182182 width : Optional [CssUnit ] = None ,
@@ -198,11 +198,12 @@ def accordion(
198198 value will correspond to the :func:`~shiny.ui.accordion_panel`'s
199199 `value` argument.
200200 open
201- A list of :func:`~shiny.ui.accordion_panel` values to open (i.e.,
202- show) by default. The default value of `None` will open the first
203- :func:`~shiny.ui.accordion_panel`. Use a value of `True` to open
204- all (or `False` to open none) of the items. It's only possible to open more than
205- one panel when `multiple=True`.
201+ A `str` or list of `str` naming the :func:`~shiny.ui.accordion_panel`
202+ value(s) to open (i.e., show) by default. (An empty list closes all panels.)
203+ The default value of `None` will open the first
204+ :func:`~shiny.ui.accordion_panel`. Use a value of `True` to open all (or `False`
205+ to open none) of the items. It's only possible to open more than one panel when
206+ `multiple=True`.
206207 multiple
207208 Whether multiple :func:`~shiny.ui.accordion_panel` can be open at
208209 once.
@@ -259,21 +260,19 @@ def accordion(
259260 )
260261 open = restore_input (accordion_id , open )
261262
262- is_open : list [bool ] = []
263- if open is None :
264- is_open = [False for _ in panels ]
263+ is_open : list [bool ]
264+ if has_restored_input and open is None :
265+ # None from restore_input indicates all panels closed
266+ is_open = [False ] * len (panels )
267+ elif open is None :
268+ # otherwise None indicates default behavior (open first panel)
269+ is_open = [i == 0 for i in range (len (panels ))]
265270 elif isinstance (open , bool ):
266- is_open = [open for _ in panels ]
271+ is_open = [open ] * len ( panels )
267272 else :
268- if not isinstance (open , list ):
269- open = [open ]
270- #
271- is_open = [panel ._data_value in open for panel in panels ]
272-
273- if not has_restored_input :
274- # Open the first panel by default
275- if open is not False and len (is_open ) > 0 and not any (is_open ):
276- is_open [0 ] = True
273+ # str | ListOrTuple[str] -> set
274+ open_set = {open } if isinstance (open , str ) else set (open )
275+ is_open = [panel ._data_value in open_set for panel in panels ]
277276
278277 if (not multiple ) and sum (is_open ) > 1 :
279278 raise ValueError ("Can't select more than one panel when `multiple = False`" )
@@ -384,11 +383,11 @@ def _accordion_panel_action(
384383 * ,
385384 id : str ,
386385 method : str ,
387- values : bool | str | list [str ],
386+ values : bool | str | ListOrTuple [str ],
388387 session : Session | None ,
389388) -> None :
390389 if not isinstance (values , bool ):
391- if not isinstance (values , list ):
390+ if not isinstance (values , ( list , tuple ) ):
392391 values = [values ]
393392 _assert_list_str (values )
394393
@@ -404,7 +403,7 @@ def _accordion_panel_action(
404403def update_accordion (
405404 id : str ,
406405 * ,
407- show : bool | str | list [str ],
406+ show : bool | str | ListOrTuple [str ],
408407 session : Optional [Session ] = None ,
409408) -> None :
410409 """
@@ -502,7 +501,7 @@ def insert_accordion_panel(
502501@add_example ()
503502def remove_accordion_panel (
504503 id : str ,
505- target : str | list [str ],
504+ target : str | ListOrTuple [str ],
506505 session : Optional [Session ] = None ,
507506) -> None :
508507 """
@@ -513,7 +512,8 @@ def remove_accordion_panel(
513512 id
514513 A string that matches an existing :func:`~shiny.ui.accordion`'s `id`.
515514 target
516- The `value` of an existing panel to remove.
515+ A string or list of strings used to identify particular
516+ :func:`~shiny.ui.accordion_panel`(s) by their `value`.
517517 session
518518 A Shiny session object (the default should almost always be used).
519519
@@ -529,7 +529,7 @@ def remove_accordion_panel(
529529 * :func:`~shiny.ui.insert_accordion_panel`
530530 * :func:`~shiny.ui.update_accordion_panel`
531531 """
532- if not isinstance (target , list ):
532+ if not isinstance (target , ( list , tuple ) ):
533533 target = [target ]
534534
535535 _send_panel_message (
@@ -632,8 +632,8 @@ def _assert_str(x: str) -> str:
632632 return x
633633
634634
635- def _assert_list_str (x : list [str ]) -> list [str ]:
636- if not isinstance (x , list ):
635+ def _assert_list_str (x : ListOrTuple [str ]) -> ListOrTuple [str ]:
636+ if not isinstance (x , ( list , tuple ) ):
637637 raise TypeError (f"Expected list, got { type (x )} " )
638638 for i , x_i in enumerate (x ):
639639 if not isinstance (x_i , str ):
0 commit comments