Repository: posit-dev/py-shiny (language: python)

Issue:
feat(tests): Add shiny.pytest, shiny.run and shiny.playwright
Fixes #1156

While more documentation will be needed, this will be done in a followup PR. If docs are not met, we can cripple the exposed classes / methods then before release.

----------------------------------------


Public API being exposed:
* `shiny`
	* `pytest`
		* `create_app_fixture()`
		* `ScopeName`; [Fixture levels for scope within pytest](https://github.com/pytest-dev/pytest/blob/0070151c630b30e38381f1a3a00e263de4665e26/src/_pytest/scope.py#L17) (not exposed)
		* `_pytest.py`
			* `local_app` fixture. Autoloaded via `pytest11` entrypoint described in setup.cfg
	* `run`
		* `run_shiny_app() -> ShinyAppProc`: Run shiny app process
		* `ShinyAppProc`: Shiny app process class. Context Manager that calls `.close()` on `__exit__()`.
	* `playwright`
		* `expect`
			* `expect_to_change()`; Wait until a Locator has updated
			* `expect_attribute_to_have_value()`
			* `expect_to_have_class()`;
			* `expect_not_to_have_class()`;
			* `expect_to_have_style()`; 
		* `controls`
			* <details>

				<summary> 
				<code>shiny.playwright.controls</code> classes. (Click to expand!)
				</summary>
				
				* `InputActionButton`
				* `InputActionLink`
				* `InputCheckbox`
				* `InputCheckboxGroup`
				* `InputDarkMode`
				* `InputDate`
				* `InputDateRange`
				* `InputFile`
				* `InputNumeric`
				* `InputPassword`
				* `InputRadioButtons`
				* `InputSelect`
				* `InputSelectize`
				* `InputSlider`
				* `InputSliderRange`
				* `InputSwitch`
				* `InputTaskButton`
				* `InputText`
				* `InputTextArea`
				* `OutputCode`
				* `OutputDataFrame`
				* `OutputImage`
				* `OutputPlot`
				* `OutputTable`
				* `OutputText`
				* `OutputTextVerbatim`
				* `OutputUi`
				* `ValueBox`
				* `Card`
				* `Accordion`
				* `Sidebar`
				* `Popover`
				* `Tooltip`
				* `NavItem`
				* `NavsetBar`
				* `NavsetCardPill`
				* `NavsetCardTab`
				* `NavsetCardUnderline`
				* `NavsetHidden`
				* `NavsetPill`
				* `NavsetPillList`
				* `NavsetTab`
				* `NavsetUnderline`
				* `DownloadButton`
				* `DownloadLink`
				
				</details>
				

---------------------------

Typical _typed_ usage:

```python
from playwright.sync_api import Page

from shiny.playwright.controls import Accordion, InputActionButton, OutputTextVerbatim
from shiny.run import ShinyAppProc
```

Typical _untyped_ usage:

```python
from shiny.playwright.controls import Accordion, InputActionButton, OutputTextVerbatim
```


Discussion / hints:
Forgot to add a change log entry

Fix patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index c01bbc04d..c012a65f1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -57,6 +57,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 
 ### New features
 
+* Expose shiny.pytest, shiny.run and shiny.playwright modules that allow users to testing their Shiny apps. (#1448, #1456)
+
 * Added busy indicators to provide users with a visual cue when the server is busy calculating outputs or otherwise serving requests to the client. More specifically, a spinner is shown on each calculating/recalculating output, and a pulsing banner is shown at the top of the page when the app is otherwise busy. Use the new `ui.busy_indicator.options()` function to customize the appearance of the busy indicators and `ui.busy_indicator.use()` to disable/enable them. (#918)
 
 * Added support for creating modules using Shiny Express syntax, and using modules in Shiny Express apps. (#1220)
diff --git a/shiny/playwright/__init__.py b/shiny/playwright/__init__.py
index 815c64b17..bc6e14e21 100644
--- a/shiny/playwright/__init__.py
+++ b/shiny/playwright/__init__.py
@@ -5,12 +5,24 @@
         "The shiny.playwright module requires the playwright package to be installed."
         " Please install it with this command:"
         "\n\n    pip install playwright"
-        "\n\n",
-        "If you are using pytest to test your code,"
-        " you can install the pytest-playwright shim package with this command:",
-        "\n\n    pip install pytest-playwright",
     )
+# If `pytest` is installed...
+try:
+    import pytest  # noqa: F401 # pyright: ignore[reportUnusedImport, reportMissingTypeStubs]
+
+    # At this point, `playwright` and `pytest` are installed.
+    # Try to make sure `pytest-playwright` is installed
+    try:
+        import pytest_playwright  # noqa: F401 # pyright: ignore[reportUnusedImport, reportMissingTypeStubs]
 
+    except ImportError:
+        raise ImportError(
+            "If you are using pytest to test your app,"
+            " you can install the pytest-playwright shim package with this command:",
+            "\n\n    pip install pytest-playwright",
+        )
+except ImportError:
+    pass
 from . import controls, expect
 
 __all__ = ["expect", "controls"]
diff --git a/shiny/playwright/controls/_controls.py b/shiny/playwright/controls/_controls.py
index b7032ea85..a86cd721b 100644
--- a/shiny/playwright/controls/_controls.py
+++ b/shiny/playwright/controls/_controls.py
@@ -111,6 +111,20 @@ def set_text(
     delay: OptionalFloat = None,
     timeout: Timeout = None,
 ) -> None:
+    """
+    Sets the text of a DOM element.
+
+    Parameters
+    ----------
+    loc
+        Playwright `Locator` of the element.
+    text
+        The text to set.
+    delay
+        The delay between key presses in milliseconds. Defaults to `None`.
+    timeout
+        The maximum time to wait for the text to be set. Defaults to `None`.
+    """
     # TODO-future; Composable set() method
     loc.fill("", timeout=timeout)  # Reset the value
     loc.type(text, delay=delay, timeout=timeout)  # Type the value
@@ -126,21 +140,37 @@ def _expect_multiple(loc: Locator, multiple: bool, timeout: Timeout = None) -> N
 ######################################################
 
 
-class _InputBaseP(Protocol):
+class _UiBaseP(Protocol):
     id: str
     loc: Locator
     page: Page
 
 
-class _InputWithContainerP(_InputBaseP, Protocol):
+class _UiWithContainerP(_UiBaseP, Protocol):
+    """A protocol class representing UI with a container."""
+
     loc_container: Locator
+    """
+    Playwright `Locator` for the container of the UI element.
+    """
+
 
+class _UiBase:
+    """A base class representing shiny UI components."""
 
-class _InputBase:
     # timeout: Timeout
     id: str
+    """
+    The browser DOM `id` of the UI element.
+    """
     loc: Locator
+    """
+    Playwright `Locator` of the UI element.
+    """
     page: Page
+    """
+    Playwright `Page` of the Shiny app.
+    """
 
     def __init__(
         self,
@@ -159,17 +189,19 @@ def __init__(
     @property
     # TODO; Can not publicly find `LocatorAssertions` in `playwright`
     def expect(self):
+        """Expectation method equivalent to `playwright.expect(self.loc)`."""
+        # TODO-karan-test: Search for `.loc)` and convert `expect(FOO.loc)` to `FOO.expect`. If we don't like the helper API, we should remove it.
         return playwright_expect(self.loc)
 
 
-class _InputWithContainer(_InputBase):
+class _UiWithContainer(_UiBase):
     """
-    A mixin class representing inputs with a container.
+    A mixin class representing UI with a container.
     """
 
     loc_container: Locator
     """
-    `loc_container` is the locator of the container of the input.
+    Playwright `Locator` for the container of the UI element.
     """
 
     def __init__(
@@ -186,13 +218,13 @@ def __init__(
         Parameters
         ----------
         page
-            The page where the input is located.
+            Playwright `Page` of the Shiny app.
         id
-            The id of the input.
+            The id of the UI element.
         loc
-            The locator of the input.
+            Playwright `Locator` of the UI element.
         loc_container
-            The locator of the container of the input.
+            Playwright `Locator` of the container of the UI element.
         """
         loc_is_str = isinstance(loc, str)
         loc_container_is_str = isinstance(loc_container, str)
@@ -225,7 +257,14 @@ def __init__(
         self.loc_container = loc_container
 
 
-class _InputWithLabel(_InputWithContainer):
+class _UiWithLabel(_UiWithContainer):
+    """A mixin class representing UI components with a label."""
+
+    loc_label: Locator
+    """
+    Playwright `Locator` for the label of the UI element.
+    """
+
     def __init__(
         self,
         page: Page,
@@ -235,6 +274,22 @@ def __init__(
         loc_container: InitLocator = "div.shiny-input-container",
         loc_label: InitLocator | None = None,
     ) -> None:
+        """
+        Initializes the input with a label.
+
+        Parameters
+        ----------
+        page
+            The page where the input is located.
+        id
+            The id of the UI element.
+        loc
+            Playwright `Locator` of the UI element.
+        loc_container
+            Playwright `Locator` of the container of the UI element.
+        loc_label
+            Playwright `Locator` of the label of the UI element. Defaults to `None`.
+        """
         super().__init__(
             page,
             id=id,
@@ -254,31 +309,41 @@ def expect_label(
         *,
         timeout: Timeout = None,
     ) -> None:
+        """
+        Expect the label of the input to have a specific text.
+
+        Parameters
+        ----------
+        value
+            The expected text value of the label.
+        timeout
+            The maximum time to wait for the expectation to be fulfilled. Defaults to `None`.
+        """
         playwright_expect(self.loc_label).to_have_text(value, timeout=timeout)
 
 
 class _WidthLocM:
     """
-    A mixin class representing the `loc`'s width.
-    This class provides methods to expect the width attribute of an element.
+    A mixin class representing the `.loc`'s width.
+
+    This class provides methods to expect the width attribute of a DOM element.
     """
 
     def expect_width(
-        self: _InputBaseP,
+        self: _UiBaseP,
         value: AttrValue,
         *,
         timeout: Timeout = None,
     ) -> None:
         """
-        Expect the width attribute of an element to have a specific value.
+        Expect the `width` attribute of a DOM element to have a specific value.
 
         Parameters
         ----------
         value
-            The expected value of the width attribute.
+            The expected value of the `width` attribute.
         timeout
-            The maximum time to wait for the expectation to be fulfilled.
-            Defaults to None.
+            The maximum time to wait for the expectation to be fulfilled. Defaults to `None`.
         """
         expect_attribute_to_have_value(self.loc, "width", value=value, timeout=timeout)
 
@@ -286,25 +351,25 @@ def expect_width(
 class _WidthContainerM:
     """
     A mixin class representing the container's width.
-    This class provides methods to expect the width attribute of an element's container.
+
+    This class provides methods to expect the width attribute of a DOM element's container.
     """
 
     def expect_width(
-        self: _InputWithContainerP,
+        self: _UiWithContainerP,
         value: AttrValue,
         *,
         timeout: Timeout = None,
     ) -> None:
         """
-        Expect the width attribute of an element's container to have a specific value.
+        Expect the `width` attribute of a input's container to have a specific value.
 
         Parameters
         ----------
         value
-            The expected value of the width attribute.
+            The expected value of the `width` attribute.
         timeout
-            The maximum time to wait for the expectation to be fulfilled.
-            Defaults to None.
+            The maximum time to wait for the expectation to be fulfilled. Defaults to `None`.
         """
         expect_attribute_to_have_value(
             self.loc_container, "width", value=value, timeout=timeout
@@ -312,17 +377,39 @@ def expect_width(
 
 
 class _SetTextM:
-    def set(self: _InputBaseP, value: str, *, timeout: Timeout = None) -> None:
+    def set(self: _UiBaseP, value: str, *, timeout: Timeout = None) -> None:
+        """
+        Sets the text value
+
+        Parameters
+        ----------
+        value
+            The text to set.
+        timeout
+            The maximum time to wait for the text to be set. Defaults to `None`.
+        """
         set_text(self.loc, value, timeout=timeout)
 
 
 class _ExpectTextInputValueM:
+    """A mixin class for text input values."""
+
     def expect_value(
-        self: _InputBaseP,
+        self: _UiBaseP,
         value: PatternOrStr,
         *,
         timeout: Timeout = None,
     ) -> None:
+        """
+        Expect the value of the text input to have a specific value.
+
+        Parameters
+        ----------
+        value
+            The expected value of the text input.
+        timeout
+            The maximum time to wait for the expectation to be fulfilled. Defaults to `None`.
+        """
         playwright_expect(self.loc).to_have_value(value, timeout=timeout)
 
 
@@ -330,17 +417,21 @@ class InputNumeric(
     _SetTextM,
     _ExpectTextInputValueM,
     _WidthLocM,
-    _InputWithLabel,
+    _UiWithLabel,
 ):
-    # id: str,
-    # label: TagChild,
-    # value: float,
-    # *,
-    # min: Optional[float] = None,
-    # max: Optional[float] = None,
-    # step: Optional[float] = None,
-    # width: Optional[str] = None,
+    """Input numeric control for :func:`~shiny.ui.input_numeric`."""
+
     def __init__(self, page: Page, id: str) -> None:
+        """
+        Initializes the input numeric Playwright control.
+
+        Parameters
+        ----------
+        page
+            The page where the input numeric is located.
+        id
+            The id of the input numeric.
+        """
         super().__init__(
             page,
             id=id,
@@ -353,6 +444,16 @@ def expect_min(
         *,
         timeout: Timeout = None,
     ) -> None:
+        """
+        Expect the minimum numeric value to be a specific value.
+
+        Parameters
+        ----------
+        value
+            The expected minimum numeric value.
+        timeout
+            The maximum time to wait for the expectation to be fulfilled. Defaults to `None`.
+        """
         expect_attribute_to_have_value(self.loc, "min", value=value, timeout=timeout)
 
     def expect_max(
@@ -361,6 +462,16 @@ def expect_max(
         *,
         timeout: Timeout = None,
     ) -> None:
+        """
+        Expect the maximum numeric value to be a specific value.
+
+        Parameters
+        ----------
+        value
+            The expected maximum numeric value.
+        timeout
+            The maximum time to wait for the expectation to be fulfilled. Defaults to `None`.
+        """
         expect_attribute_to_have_value(self.loc, "max", value=value, timeout=timeout)
 
     def expect_step(
@@ -369,16 +480,40 @@ def expect_step(
         *,
         timeout: Timeout = None,
     ) -> None:
+        """
+        Expect step value when incrementing/decrementing the numeric input.
+
+        Parameters
+        ----------
+        value
+            The expected step value for the numeric input.
+        timeout
+            The maximum time to wait for the expectation to be fulfilled. Defaults to `None`.
+        """
         expect_attribute_to_have_value(self.loc, "step", value=value, timeout=timeout)
 
 
 class _ExpectSpellcheckAttrM:
+    """
+    A mixin class for the spellcheck attribute.
+    """
+
     def expect_spellcheck(
-        self: _InputBaseP,
+        self: _UiBaseP,
         value: Literal["true", "false"] | None,
         *,
         timeout: Timeout = None,
     ) -> None:
+        """
+        Expect the `spellcheck` attribute of the input to have a specific value.
+
+        Parameters
+        ----------
+        value
+            The expected value of the `spellcheck` attribute.
+        timeout
+            The maximum time to wait for the expectation to be fulfilled. Defaults to `None`.
+        """
         # self.spellcheck.expect_to_have_value(value, timeout=timeout)
         expect_attribute_to_have_value(
             self.loc, "spellcheck", value=value, timeout=timeout
@@ -387,11 +522,21 @@ def expect_spellcheck(
 
 class _ExpectPlaceholderAttrM:
     def expect_placeholder(
-        self: _InputBaseP,
+        self: _UiBaseP,
         value: AttrValue,
         *,
         timeout: Timeout = None,
     ) -> None:
+        """
+        Expect the `placeholder` attribute of the input to have a specific value.
+
+        Parameters
+        ----------
+        value
+            The expected value of the `placeholder` attribute.
+        timeout
+            The maximum time to wait for the expectation to be fulfilled. Defaults to `None`.
+        """
         expect_attribute_to_have_value(
             self.loc, "placeholder", value=value, timeout=timeout
         )
@@ -399,11 +544,21 @@ def expect_placeholder(
 
 class _ExpectAutocompleteAttrM:
     def expect_autocomplete(
-        self: _InputBaseP,
+        self: _UiBaseP,
         value: AttrValue,
         *,
         timeout: Timeout = None,
     ) -> None:
+        """
+        Expect the `autocomplete` attribute of the input to have a specific value.
+
+        Parameters
+        ----------
+        value
+            The expected value of the `autocomplete` attribute.
+        timeout
+            The maximum time to wait for the expectation to be fulfilled. Defaults to `None`.
+        """
         expect_attribute_to_have_value(
             self.loc, "autocomplete", value=value, timeout=timeout
         )
@@ -416,17 +571,21 @@ class InputText(
     _ExpectPlaceholderAttrM,
     _ExpectAutocompleteAttrM,
     _ExpectSpellcheckAttrM,
-    _InputWithLabel,
+    _UiWithLabel,
 ):
-    # id: str,
-    # label: TagChild,
-    # value: str = "",
-    # *,
-    # width: Optional[str] = None,
-    # placeholder: Optional[str] = None,
-    # autocomplete: Optional[str] = "off",
-    # spellcheck: Optional[Literal["true", "false"]] = None,
+    """Input text control for :func:`~shiny.ui.input_text`."""
+
     def __init__(self, page: Page, id: str) -> None:
+        """
+        Initializes the input text.
+
+        Parameters
+        ----------
+        page
+            The page where the input text is located.
+        id
+            The id of the input text.
+        """
         super().__init__(
             page,
             id=id,
@@ -438,17 +597,21 @@ class InputPassword(
     _SetTextM,
     _ExpectTextInputValueM,
     _ExpectPlaceholderAttrM,
-    _InputWithLabel,
+    _UiWithLabel,
 ):
-    # id: str,
-    # label: TagChild,
-    # value: str = "",
-    # *,
-    # width: Optional[str] = None,
-    # placeholder: Optional[str] = None,
-    ...
+    """Input password control for :func:`~shiny.ui.input_password`."""
 
     def __init__(self, page: Page, id: str) -> None:
+        """
+        Initializes the input password.
+
+        Parameters
+        ----------
+        page
+            The page where the input password is located.
+        id
+            The id of the input password.
+        """
         super().__init__(
             page,
             id=id,
@@ -463,6 +626,16 @@ def expect_width(
         *,
         timeout: Timeout = None,
     ) -> None:
+        """
+        Expect the `width` attribute of the input password to have a specific value.
+
+        Parameters
+        ----------
+        value
+            The expected value of the `width` attribute.
+        timeout
+            The maximum time to wait for the expectation to be fulfilled. Defaults to `None`.
+        """
         expect_to_have_style(self.loc_container, "width", value, timeout=timeout)
 
 
@@ -475,22 +648,21 @@ class InputTextArea(
     _ExpectPlaceholderAttrM,
     _ExpectAutocompleteAttrM,
     _ExpectSpellcheckAttrM,
-    _InputWithLabel,
+    _UiWithLabel,
 ):
-    # id: str,
-    # label: TagChild,
-    # value: str = "",
-    # width: Optional[str] = None,
-    # height: Optional[str] = None,
-    # cols: Optional[int] = None,
-    # rows: Optional[int] = None,
-    # placeholder: Optional[str] = None,
-    # resize: Optional[
-    #     Literal["none", "both", "horizontal", "vertical"]
-    # ] = None,
-    # autocomplete: Optional[str] = None,
-    # spellcheck: Optional[Literal["true", "false"]] = None,
+    """Input text area control for :func:`~shiny.ui.input_text_area`."""
+
     def __init__(self, page: Page, id: str) -> None:
+        """
+        Initializes the input text area.
+
+        Parameters
+        ----------
+        page
+            The page where the input text area is located.
+        id
+            The id of the input text area.
+        """
         super().__init__(
             page,
             id=id,
@@ -498,6 +670,16 @@ def __init__(self, page: Page, id: str) -> None:
         )
 
     def expect_width(self, value: StyleValue, *, timeout: Timeout = None) -> None:
+        """
+        Expect the `width` attribute of the input text area to have a specific value.
+
+        Parameters
+        ----------
+        value
+            The expected value of the `width` attribute.
+        timeout
+            The maximum time to wait for the expectation to be fulfilled. Defaults to `None`.
+        """
         if value is None:
             expect_to_have_style(self.loc_container, "width", None, timeout=timeout)
             expect_to_have_style(self.loc, "width", "100%", timeout=timeout)
@@ -506,12 +688,42 @@ def expect_width(self, value: StyleValue, *, timeout: Timeout = None) -> None:
             expect_to_have_style(self.loc, "width", None, timeout=timeout)
 
     def expect_height(self, value: StyleValue, *, timeout: Timeout = None) -> None:
+        """
+        Expect the `height` attribute of the input text area to have a specific value.
+
+        Parameters
+        ----------
+        value
+            The expected value of the `height` attribute.
+        timeout
+            The maximum time to wait for the expectation to be fulfilled. Defaults to `None`.
+        """
         expect_to_have_style(self.loc, "height", value, timeout=timeout)
 
     def expect_cols(self, value: AttrValue, *, timeout: Timeout = None) -> None:
+        """
+        Expect the `cols` attribute of the input text area to have a specific value.
+
+        Parameters
+        ----------
+        value
+            The expected value of the `cols` attribute.
+        timeout
+            The maximum time to wait for the expectation to be fulfilled. Defaults to `None`.
+        """
         expect_attribute_to_have_value(self.loc, "cols", value=value, timeout=timeout)
 
     def expect_rows(self, value: AttrValue, *, timeout: Timeout = None) -> None:
+        """
+        Expect the `rows` attribute of the input text area to have a specific value.
+
+        Parameters
+        ----------
+        value
+            The expected value of the `rows` attribute.
+        timeout
+            The maximum time to wait for the expectation to be fulfilled. Defaults to `None`.
+        """
         expect_attribute_to_have_value(self.loc, "rows", value=value, timeout=timeout)
 
     def expect_resize(
@@ -520,6 +732,16 @@ def expect_resize(
         *,
         timeout: Timeout = None,
     ) -> None:
+        """
+        Expect the `resize` attribute of the input text area to have a specific value.
+
+        Parameters
+        ----------
+        value
+            The expected value of the `resize` attribute.
+        timeout
+            The maximum time to wait for the expectation to be fulfilled. Defaults to `None`.
+        """
         expect_attribute_to_have_value(self.loc, "resize", value=value, timeout=timeout)
 
     def expect_autoresize(
@@ -528,6 +750,16 @@ def expect_autoresize(
         *,
         timeout: Timeout = None,
     ) -> None:
+        """
+        Expect the `autoresize` attribute of the input text area to have a specific value.
+
+        Parameters
+        ----------
+        value
+            The expected value of the `autoresize` attribute.
+        timeout
+            The maximum time to wait for the expectation to be fulfilled. Defaults to `None`.
+        """
         _expect_class_value(
             self.loc,
             "textarea-autoresize",
@@ -538,11 +770,20 @@ def expect_autoresize(
 
 class _InputSelectBase(
     _WidthLocM,
-    _InputWithLabel,
+    _UiWithLabel,
 ):
     loc_selected: Locator
+    """
+    Playwright `Locator` for the selected option of the input select.
+    """
     loc_choices: Locator
+    """
+    Playwright `Locator` for the choices of the input select.
+    """
     loc_choice_groups: Locator
+    """
+    Playwright `Locator` for the choice groups of the input select.
+    """
 
     def __init__(
         self,
@@ -551,6 +792,18 @@ def __init__(
         *,
         select_class: str = "",
     ) -> None:
+        """
+        Initializes the input select.
+
+        Parameters
+        ----------
+        page
+            The page where the input select is located.
+        id
+            The id of the input select.
+        select_class
+            The class of the select element. Defaults to "".
+        """
         super().__init__(
             page,
             id=id,
@@ -566,6 +819,16 @@ def set(
         *,
         timeout: Timeout = None,
     ) -> None:
+        """
+        Sets the selected option(s) of the input select.
+
+        Parameters
+        ----------
+        selected
+            The value(s) of the selected option(s).
+        timeout
+            The maximum time to wait for the selection to be set. Defaults to `None`.
+        """
         if isinstance(selected, str):
             selected = [selected]
         self.loc.select_option(value=selected, timeout=timeout)
@@ -577,7 +840,17 @@ def expect_choices(
         *,
         timeout: Timeout = None,
     ) -> None:
-        """Expect choices to be in order"""
+        """
+        Expect the available options of the input select to be an exact match.
+
+        Parameters
+        ----------
+        choices
+            The expected choices of the input select.
+        timeout
+            The maximum time to wait for the expectation to be fulfilled. Defaults to `None`.
+        """
+
         # Playwright doesn't like lists of size 0. Instead, check for empty locator
         if len(choices) == 0:
             playwright_expect(self.loc_choices).to_have_count(0, timeout=timeout)
@@ -594,20 +867,29 @@ def expect_choices(
 
     def expect_selected(
         self,
-        selected: PatternOrStr | ListPatternOrStr,
+        value: PatternOrStr | ListPatternOrStr,
         *,
         timeout: Timeout = None,
     ) -> None:
-        """Expect choices to be in order"""
+        """
+        Expect the selected option(s) of the input select to be an exact match.
+
+        Parameters
+        ----------
+        value
+            The expected value(s) of the selected option(s).
+        timeout
+            The maximum time to wait for the expectation to be fulfilled. Defaults to `None`.
+        """
         # Playwright doesn't like lists of size 0
-        if isinstance(selected, list) and len(selected) == 0:
+        if isinstance(value, list) and len(value) == 0:
             playwright_expect(self.loc_selected).to_have_count(0, timeout=timeout)
             return
 
-        if isinstance(selected, list):
-            self.expect.to_have_values(selected, timeout=timeout)
+        if isinstance(value, list):
+            self.expect.to_have_values(value, timeout=timeout)
         else:
-            self.expect.to_have_value(selected, timeout=timeout)
+            self.expect.to_have_value(value, timeout=timeout)
 
         # _MultipleDomItems.expect_locator_values_in_list(
         #     page=self.page,
@@ -626,7 +908,17 @@ def expect_choice_groups(
         *,
         timeout: Timeout = None,
     ) -> None:
-        """Expect choices to be in order"""
+        """
+        Expect the choice groups of the input select to be an exact match.
+
+        Parameters
+        ----------
+        choice_groups
+            The expected choice groups of the input select.
+        timeout
+            The maximum time to wait for the expectation to be fulfilled. Defaults to `None`.
+        """
+
         # Playwright doesn't like lists of size 0. Instead, use `None`
         if len(choice_groups) == 0:
             playwright_expect(self.loc_choice_groups).to_have_count(0, timeout=timeout)
@@ -644,21 +936,51 @@ def expect_choice_groups(
 
     def expect_choice_labels(
         self,
-        choice_labels: ListPatternOrStr,
+        value: ListPatternOrStr,
         *,
         timeout: Timeout = None,
     ) -> None:
+        """
+        Expect the choice labels of the input select to be an exact match.
+
+        Parameters
+        ----------
+        value
+            The expected choice labels of the input select.
+        timeout
+            The maximum time to wait for the expectation to be fulfilled. Defaults to `None`.
+        """
         # Playwright doesn't like lists of size 0. Instead, use `None`
-        if len(choice_labels) == 0:
+        if len(value) == 0:
             playwright_expect(self.loc_choices).to_have_count(0, timeout=timeout)
             return
-        playwright_expect(self.loc_choices).to_have_text(choice_labels, timeout=timeout)
+        playwright_expect(self.loc_choices).to_have_text(value, timeout=timeout)
 
     # multiple: bool = False,
-    def expect_multiple(self, multiple: bool, *, timeout: Timeout = None) -> None:
-        _expect_multiple(self.loc, multiple, timeout=timeout)
+    def expect_multiple(self, value: bool, *, timeout: Timeout = None) -> None:
+        """
+        Expect the input select to allow multiple selections.
+
+        Parameters
+        ----------
+        value
+            Whether the input select allows multiple selections.
+        timeout
+            The maximum time to wait for the expectation to be fulfilled. Defaults to `None`.
+        """
+        _expect_multiple(self.loc, value, timeout=timeout)
 
     def expect_size(self, value: AttrValue, *, timeout: Timeout = None) -> None:
+        """
+        Expect the size attribute of the input select to have a specific value.
+
+        Parameters
+        ----------
+        value
+            The expected value of the `size` attribute.
+        timeout
+            The maximum time to wait for the expectation to be fulfilled. Defaults to `None`.
+        """
         expect_attribute_to_have_value(
             self.loc,
             "size",
@@ -668,15 +990,19 @@ def expect_size(self, value: AttrValue, *, timeout: Timeout = None) -> None:
 
 
 class InputSelect(_InputSelectBase):
-    # id: str,
-    # label: TagChild,
-    # choices: SelectChoicesArg,
-    # selected: Optional[Union[str, list[str]]] = None,
-    # multiple: bool = False,
-    # selectize: bool = False,
-    # width: Optional[str] = None,
-    # size: Optional[str] = None,
+    """Input select control for :func:`~shiny.ui.input_select`."""
+
     def __init__(self, page: Page, id: str) -> None:
+        """
+        Initializes the input select.
+
+        Parameters
+        ----------
+        page
+            The page where the input select is located.
+        id
+            The id of the input select.
+        """
         super().__init__(
             page,
             id=id,
@@ -684,17 +1010,29 @@ def __init__(self, page: Page, id: str) -> None:
         )
 
     # selectize: bool = False,
-    def expect_selectize(self, selectize: bool, *, timeout: Timeout = None) -> None:
+    def expect_selectize(self, value: bool, *, timeout: Timeout = None) -> None:
+        """
+        Expect the input select to be selectize.
+
+        Parameters
+        ----------
+        value
+            Whether the input select is selectize.
+        timeout
+            The maximum time to wait for the expectation to be fulfilled. Defaults to `None`.
+        """
         # class_=None if selectize else "form-select",
         _expect_class_value(
             self.loc,
             "form-select",
-            has_class=not selectize,
+            has_class=not value,
             timeout=timeout,
         )
 
 
 class InputSelectize(_InputSelectBase):
+    """Input selectize control for :func:`~shiny.ui.input_selectize`."""
+
     def __init__(self, page: Page, id: str) -> None:
         super().__init__(
             page,
@@ -703,18 +1041,37 @@ def __init__(self, page: Page, id: str) -> None:
         )
 
 
-class _InputActionBase(_InputBase):
+class _InputActionBase(_UiBase):
     def expect_label(
         self,
         value: PatternOrStr,
         *,
         timeout: Timeout = None,
     ) -> None:
-        """Must include icon if present"""
+        """
+        Expect the label of the input button to have a specific value.
+
+        Note: This must include the icon if it is present!
+
+        Parameters
+        ----------
+        value
+            The expected value of the label.
+        timeout
+            The maximum time to wait for the expectation to be fulfilled. Defaults to `None`.
+        """
 
         self.expect.to_have_text(value, timeout=timeout)
 
     def click(self, *, timeout: Timeout = None, **kwargs: object) -> None:
+        """
+        Clicks the input action.
+
+        Parameters
+        ----------
+        timeout
+            The maximum time to wait for the input action to be clicked. Defaults to `None`.
+        """
         self.loc.click(timeout=timeout, **kwargs)  # pyright: ignore[reportArgumentType]
 
 
@@ -722,15 +1079,23 @@ class InputActionButton(
     _WidthLocM,
     _InputActionBase,
 ):
-    # label: TagChild,
-    # icon: TagChild = None,
-    # width: Optional[str] = None,
+    """Input action button control for :func:`~shiny.ui.input_action_button`."""
 
     def __init__(
         self,
         page: Page,
         id: str,
     ) -> None:
+        """
+        Initializes the input action button.
+
+        Parameters
+        ----------
+        page
+            The page where the input action button is located.
+        id
+            The id of the input action button.
+        """
         super().__init__(
             page,
             id=id,
@@ -738,12 +1103,24 @@ def __init__(
         )
 
 
-class InputDarkMode(_InputBase):
+class InputDarkMode(_UiBase):
+    """Input dark mode control for :func:`~shiny.ui.input_dark_mode`."""
+
     def __init__(
         self,
         page: Page,
         id: Optional[str] | None,
     ) -> None:
+        """
+        Initializes the input dark mode.
+
+        Parameters
+        ----------
+        page
+            The page where the input dark mode is located.
+        id
+            The id of the input dark mode.
+        """
         id_selector = "" if id is None else f"#{id}"
 
         super().__init__(
@@ -753,21 +1130,59 @@ def __init__(
         )
 
     def click(self, *, timeout: Timeout = None):
+        """
+        Clicks the input dark mode.
+
+        Parameters
+        ----------
+        timeout
+            The maximum time to wait for the input dark mode to be clicked. Defaults to `None`.
+        """
         self.loc.click(timeout=timeout)
         return self
 
     def expect_mode(self, value: str, *, timeout: Timeout = None):
+        """
+        Expect the `mode` attribute of the input dark mode to have a specific value.
+
+        Parameters
+        ----------
+        value
+            The expected value of the `mode` attribute.
+        timeout
+            The maximum time to wait for the expectation to be fulfilled. Defaults to `None`.
+        """
         expect_attribute_to_have_value(self.loc, "mode", value=value, timeout=timeout)
         self.expect_page_mode(value, timeout=timeout)
         return self
 
     def expect_page_mode(self, value: str, *, timeout: Timeout = None):
+        """
+        Expect the page to have a specific dark mode value.
+
+        Parameters
+        ----------
+        value
+            The expected value of the page's dark mode.
+        timeout
+            The maximum time to wait for the expectation to be fulfilled. Defaults to `None`.
+        """
         expect_attribute_to_have_value(
             self.page.locator("html"), "data-bs-theme", value=value, timeout=timeout
         )
         return self
 
     def expect_wc_attribute(self, value: str, *, timeout: Timeout = None):
+        """
+        Expect the `wc` attribute of the input dark mode to have a specific value.
+
+        Parameters
+        ----------
+        value
+            The expected value of the `wc` attribute.
+        timeout
+            The maximum time to wait for the expectation to be fulfilled. Defaults to `None`.
+        """
         expect_attribute_to_have_value(
             self.loc, "attribute", value=value, timeout=timeout
         )
@@ -778,22 +1193,24 @@ class InputTaskButton(
     _WidthLocM,
     _InputActionBase,
 ):
+    """Input task button control for :func:`~shiny.ui.input_task_button`."""
+
     # TODO-Karan: Test auto_reset functionality
-    # id: str,
-    # label: TagChild,
-    # *args: TagChild,
-    # icon: TagChild = None,
-    # label_busy: TagChild = "Processing...",
-    # icon_busy: TagChild | MISSING_TYPE = MISSING,
-    # width: Optional[str] = None,
-    # type: Optional[str] = "primary",
-    # auto_reset: bool = True,
-    # **kwargs: TagAttrValue,
     def __init__(
         self,
         page: Page,
         id: str,
     ) -> None:
+        """
+        Initializes the input task button.
+
+        Parameters
+        ----------
+        page
+            The page where the input task button is located.
+        id
+            The id of the input task button.
+        """
         super().__init__(
             page,
             id=id,
@@ -801,8 +1218,21 @@ def __init__(
         )
 
     def expect_state(
-        self, value: Literal["ready", "busy"] | str, *, timeout: Timeout = None
+        self,
+        value: Literal["ready", "busy"] | str,
+        *,
+        timeout: Timeout = None,
     ):
+        """
+        Expect the state of the input task button to have a specific value.
+
+        Parameters
+        ----------
+        value
+            The expected value of the state of the input task button.
+        timeout
+            The maximum time to wait for the expectation to be fulfilled. Defaults to `None`.
+        """
         expect_attribute_to_have_value(
             self.loc.locator("> bslib-switch-inline"),
             name="case",
@@ -811,22 +1241,78 @@ def expect_state(
         )
 
     def expect_label(self, value: PatternOrStr, *, timeout: Timeout = None) -> None:
+        """
+        Expect the label of the input task button to have a specific value.
+
+        Parameters
+        ----------
+        value
+            The expected value of the label.
+        timeout
+            The maximum time to wait for the expectation to be fulfilled. Defaults to `None`.
+        """
         self.expect_label_ready(value, timeout=timeout)
 
     def expect_label_ready(self, value: PatternOrStr, *, timeout: Timeout = None):
+        """
+        Expect the label of a ready input task button to have a specific value.
+
+        Parameters
+        ----------
+        value
+            The expected value of the label.
+        timeout
+            The maximum time to wait for the expectation to be fulfilled. Defaults to `None`.
+        """
         self.expect_label_state("ready", value, timeout=timeout)
 
     def expect_label_busy(self, value: PatternOrStr, *, timeout: Timeout = None):
+        """
+        Expect the label of a busy input task button to have a specific value.
+
+        Parameters
+        ----------
+        value
+            The expected value of the label.
+        timeout
+            The maximum time to wait for the expectation to be fulfilled. Defaults to `None`.
+        """
         self.expect_label_state("busy", value, timeout=timeout)
 
     def expect_label_state(
-        self, state: str, value: PatternOrStr, *, timeout: Timeout = None
+        self,
+        state: str,
+        value: PatternOrStr,
+        *,
+        timeout: Timeout = None,
     ):
+        """
+        Expect the label of the input task button to have a specific value in a specific state.
+
+        Parameters
+        ----------
+        state
+            The state of the input task button.
+        value
+            The expected value of the label.
+        timeout
+            The maximum time to wait for the expectation to be fulfilled. Defaults to `None`.
+        """
         playwright_expect(
             self.loc.locator(f"> bslib-switch-inline > span[slot='{state}']")
         ).to_have_text(value, timeout=timeout)
 
     def expect_auto_reset(self, value: bool, timeout: Timeout = None):
+        """
+        Expect the `auto-reset` attribute of the input task button to have a specific value.
+
+        Parameters
+        ----------
+        value
+            The expected value of the `auto-reset` attribute.
+        timeout
+            The maximum time to wait for the expectation to be fulfilled. Defaults to `None`.
+        """
         expect_attribute_to_have_value(
             self.loc,
             name="data-auto-reset",
@@ -836,14 +1322,23 @@ def expect_auto_reset(self, value: bool, timeout: Timeout = None):
 
 
 class InputActionLink(_InputActionBase):
-    # label: TagChild,
-    # icon: TagChild = None,
+    """Input action link control for :func:`~shiny.ui.input_action_link`."""
 
     def __init__(
         self,
         page: Page,
         id: str,
     ) -> None:
+        """
+        Initializes the input action link.
+
+        Parameters
+        ----------
+        page
+            The page where the input action link is located.
+        id
+            The id of the input action link.
+        """
         super().__init__(
             page,
             id=id,
@@ -858,14 +1353,25 @@ def __init__(
 
 class _InputCheckboxBase(
     _WidthContainerM,
-    _InputWithLabel,
+    _UiWithLabel,
 ):
-    # label: TagChild
-    # value: bool = False
-    # width: Optional[str] = None
     def __init__(
         self, page: Page, id: str, loc: InitLocator, loc_label: str | None
     ) -> None:
+        """
+        Initializes the input checkbox.
+
+        Parameters
+        ----------
+        page
+            The page where the input checkbox is located.
+        id
+            The id of the input checkbox.
+        loc
+            Playwright `Locator` of the input checkbox.
+        loc_label
+            Playwright `Locator` of the label of the input checkbox.
+        """
         super().__init__(
             page,
             id=id,
@@ -874,6 +1380,16 @@ def __init__(
         )
 
     def set(self, value: bool, *, timeout: Timeout = None, **kwargs: object) -> None:
+        """
+        Sets the input checkbox.
+
+        Parameters
+        ----------
+        value
+            The value of the input checkbox.
+        timeout
+            The maximum time to wait for the input checkbox to be set. Defaults to `None`.
+        """
         self.loc.wait_for(state="visible", timeout=timeout)
         self.loc.scroll_into_view_if_needed(timeout=timeout)
         self.loc.set_checked(
@@ -881,11 +1397,29 @@ def set(self, value: bool, *, timeout: Timeout = None, **kwargs: object) -> None
         )
 
     def toggle(self, *, timeout: Timeout = None, **kwargs: object) -> None:
+        """
+        Toggles the input checkbox.
+
+        Parameters
+        ----------
+        timeout
+            The maximum time to wait for the input checkbox to be toggled. Defaults to `None`.
+        """
         self.loc.wait_for(state="visible", timeout=timeout)
         self.loc.scroll_into_view_if_needed(timeout=timeout)
         self.loc.click(timeout=timeout, **kwargs)  # pyright: ignore[reportArgumentType]
 
     def expect_checked(self, value: bool, *, timeout: Timeout = None) -> None:
+        """
+        Expect the input checkbox to be checked.
+
+        Parameters
+        ----------
+        value
+            Whether the input checkbox is checked.
+        timeout
+            The maximum time to wait for the expectation to be fulfilled. Defaults to `None`.
+        """
         if value:
             self.expect.to_be_checked(timeout=timeout)
         else:
@@ -893,11 +1427,23 @@ def expect_checked(self, value: bool, *, timeout: Timeout = None) -> None:
 
 
 class InputCheckbox(_InputCheckboxBase):
+    """Input checkbox control for :func:`~shiny.ui.input_checkbox`."""
+
     def __init__(
         self,
         page: Page,
         id: str,
     ) -> None:
+        """
+        Initializes the input checkbox.
+
+        Parameters
+        ----------
+        page
+            The page where the input checkbox is located.
+        id
+            The id of the input checkbox.
+        """
         super().__init__(
             page,
             id=id,
@@ -907,11 +1453,23 @@ def __init__(
 
 
 class InputSwitch(_InputCheckboxBase):
+    """Input switch control for :func:`~shiny.ui.input_switch`."""
+
     def __init__(
         self,
         page: Page,
         id: str,
     ) -> None:
+        """
+        Initializes the input switch.
+
+        Parameters
+        ----------
+        page
+            The page where the input switch is located.
+        id
+            The id of the input switch.
+        """
         super().__init__(
             page,
             id=id,
@@ -926,12 +1484,30 @@ def assert_arr_is_unique(
         arr: ListPatternOrStr,
         msg: str,
     ) -> None:
+        """
+        Assert that the array is unique.
+
+        Parameters
+        ----------
+        arr
+            The array to check.
+        msg
+            The error message.
+        """
         assert len(arr) == len(list(dict.fromkeys(arr))), msg
 
     @staticmethod
     def checked_css_str(
         is_checked: bool | MISSING_TYPE = MISSING,
     ) -> str:
+        """
+        Get the CSS string for checked elements.
+
+        Parameters
+        ----------
+        is_checked
+            Whether the elements are checked. Defaults to `MISSING`.
+        """
         if is_missing(is_checked):
             return ""
         if is_checked:
@@ -952,6 +1528,31 @@ def expect_locator_contains_values_in_list(
         timeout: Timeout = None,
         key: str = "value",
     ) -> None:
+        """
+        Expect the locator to contain the values in the list.
+
+        The matching values must exist and be in order, but other values may also exist
+        within the container.
+
+        Parameters
+        ----------
+        page
+            Playwright `Page` of the Shiny app.
+        loc_container
+            The container locator.
+        el_type
+            The element type.
+        arr_name
+            The variable name.
+        arr
+            The expected values.
+        is_checked
+            Whether the elements are checked. Defaults to `MISSING`.
+        timeout
+            The timeout for the expectation. Defaults to `None`.
+        key
+            The key. Defaults to `"value"`.
+        """
         # Make sure the locator contains all of `arr`
 
         assert_type(arr, typing.List[str])
@@ -1015,6 +1616,31 @@ def expect_locator_values_in_list(
         timeout: Timeout = None,
         key: str = "value",
     ) -> None:
+        """
+        Expect the locator to contain the values in the list.
+
+        The matching values must exist and be in order. No other matching values will be
+        allowed within the container.
+
+        Parameters
+        ----------
+        page
+            Playwright `Page` of the Shiny app.
+        loc_container
+            The container locator.
+        el_type
+            The element type locator.
+        arr_name
+            The array name.
+        arr
+            The expected values.
+        is_checked
+            Whether the elements are checked. Defaults to `MISSING`.
+        timeout
+            The timeout for the expectation. Defaults to `None`.
+        key
+            The key. Defaults to `"value"`.
+        """
         # Make sure the locator has exactly `arr` values
 
         # Make sure the locator has len(uniq_arr) input elements
@@ -1083,29 +1709,52 @@ def expect_locator_values_in_list(
             raise e
 
 
-class _RadioButtonCheckboxGroupBase(_InputWithLabel):
+# TODO-barret; continue from here
+
+
+class _RadioButtonCheckboxGroupBase(_UiWithLabel):
     loc_choice_labels: Locator
 
     def expect_choice_labels(
         self,
-        labels: ListPatternOrStr,
+        value: ListPatternOrStr,
         *,
         timeout: Timeout = None,
     ) -> None:
-        if len(labels) == 1:
-            labels_val = labels[0]
+        """
+        Expect the labels of the choices.
+
+        Parameters
+        ----------
+        value
+            The expected labels.
+        timeout
+            The timeout for the expectation. Defaults to `None`.
+        """
+        if len(value) == 1:
+            labels_val = value[0]
         else:
-            labels_val = labels
+            labels_val = value
         playwright_expect(self.loc_choice_labels).to_have_text(
             labels_val,
             timeout=timeout,
         )
 
-    def expect_inline(self, inline: bool, *, timeout: Timeout = None) -> None:
+    def expect_inline(self, value: bool, *, timeout: Timeout = None) -> None:
+        """
+        Expect the input to be inline.
+
+        Parameters
+        ----------
+        value
+            Whether the input is inline.
+        timeout
+            The timeout for the expectation. Defaults to `None`.
+        """
         _expect_class_value(
             self.loc_container,
             "shiny-input-container-inline",
-            has_class=inline,
+            has_class=value,
             timeout=timeout,
         )
 
@@ -1124,6 +1773,16 @@ def __init__(
         page: Page,
         id: str,
     ) -> None:
+        """
+        Initialize the InputCheckboxGroup.
+
+        Parameters
+        ----------
+        page
+            Playwright `Page` of the Shiny app.
+        id
+            The id of the checkbox group.
+        """
         super().__init__(
             page,
             id=id,
@@ -1159,6 +1818,16 @@ def set(
         timeout: Timeout = None,
         **kwargs: object,
     ) -> None:
+        """
+        Set the selected checkboxes.
+
+        Parameters
+        ----------
+        selected
+            The values of the selected checkboxes.
+        timeout
+            The timeout for the action. Defaults to `None`.
+        """
         # Having an arr of size 0 is allowed. Will uncheck everything
         assert_type(selected, typing.List[str])
 
@@ -1197,27 +1866,47 @@ def in_selected(value: str) -> bool:
 
     def expect_choices(
         self,
-        choices: ListPatternOrStr,
+        value: ListPatternOrStr,
         *,
         timeout: Timeout = None,
     ) -> None:
+        """
+        Expect the checkbox choices.
+
+        Parameters
+        ----------
+        value
+            The expected choices.
+        timeout
+            The timeout for the expectation. Defaults to `None`.
+        """
         _MultipleDomItems.expect_locator_values_in_list(
             page=self.page,
             loc_container=self.loc_container,
             el_type="input[type=checkbox]",
             arr_name="choices",
-            arr=choices,
+            arr=value,
             timeout=timeout,
         )
 
     def expect_selected(
         self,
-        selected: ListPatternOrStr,
+        value: ListPatternOrStr,
         *,
         timeout: Timeout = None,
     ) -> None:
+        """
+        Expect the selected checkboxes.
+
+        Parameters
+        ----------
+        value
+            The expected values of the selected checkboxes.
+        timeout
+            The timeout for the expectation. Defaults to `None`.
+        """
         # Playwright doesn't like lists of size 0
-        if len(selected) == 0:
+        if len(value) == 0:
             playwright_expect(self.loc_selected).to_have_count(0, timeout=timeout)
             return
 
@@ -1226,7 +1915,7 @@ def expect_selected(
             loc_container=self.loc_container,
             el_type="input[type=checkbox]",
             arr_name="selected",
-            arr=selected,
+            arr=value,
             timeout=timeout,
             is_checked=True,
         )
@@ -1236,17 +1925,35 @@ class InputRadioButtons(
     _WidthContainerM,
     _RadioButtonCheckboxGroupBase,
 ):
-    # id: str,
-    # label: TagChild,
-    # choices: ChoicesArg,
-    # selected: Optional[str] = None,
-    # inline: bool = False,
-    # width: Optional[str] = None,
+    """Input radio buttons control for :func:`~shiny.ui.input_radio_buttons`."""
+
+    loc_selected: Locator
+    """
+    Playwright `Locator` of the selected radio button.
+    """
+    loc_choices: Locator
+    """
+    Playwright `Locator` of the radio button choices.
+    """
+    loc_choice_labels: Locator
+    """
+    Playwright `Locator` of the labels of the radio button choices.
+    """
+
     def __init__(
         self,
         page: Page,
         id: str,
     ) -> None:
+        """Initialize the InputRadioButtons.
+
+        Parameters
+        ----------
+        page
+            Playwright `Page` of the Shiny app.
+        id
+            The id of the radio buttons.
+        """
         super().__init__(
             page,
             id=id,
@@ -1281,6 +1988,16 @@ def set(
         timeout: Timeout = None,
         **kwargs: object,
     ) -> None:
+        """
+        Set the selected radio button.
+
+        Parameters
+        ----------
+        selected
+            The value of the selected radio button.
+        timeout
+            The timeout for the action. Defaults to `None`.
+        """
         assert_type(selected, str)
         # Only need to set.
         # The Browser will _unset_ the previously selected radio button
@@ -1290,40 +2007,71 @@ def set(
 
     def expect_choices(
         self,
-        choices: ListPatternOrStr,
+        value: ListPatternOrStr,
         *,
         timeout: Timeout = None,
     ) -> None:
+        """
+        Expect the radio button choices.
+
+        Parameters
+        ----------
+        value
+            The expected choices.
+        timeout
+            The timeout for the expectation. Defaults to `None`.
+        """
         _MultipleDomItems.expect_locator_values_in_list(
             page=self.page,
             loc_container=self.loc_container,
             el_type="input[type=radio]",
             arr_name="choices",
-            arr=choices,
+            arr=value,
             timeout=timeout,
         )
 
     def expect_selected(
         self,
-        selected: PatternOrStr | None,
+        value: PatternOrStr | None,
         *,
         timeout: Timeout = None,
     ) -> None:
+        """
+        Expect the selected radio button.
+
+        Parameters
+        ----------
+        value
+            The expected value of the selected radio button.
+        timeout
+            The timeout for the expectation. Defaults to `None`.
+        """
         # Playwright doesn't like lists of size 0. Instead, use `None`
-        if selected is None:
+        if value is None:
             playwright_expect(self.loc_selected).to_have_count(0, timeout=timeout)
             return
 
-        playwright_expect(self.loc_selected).to_have_value(selected, timeout=timeout)
+        playwright_expect(self.loc_selected).to_have_value(value, timeout=timeout)
 
 
 class InputFile(
     # _ExpectPlaceholderAttrM,
-    _InputWithLabel,
+    _UiWithLabel,
 ):
+    """Input file control for :func:`~shiny.ui.input_file`."""
+
     loc_button: Locator
+    """
+    Playwright `Locator` of the button.
+    """
     loc_file_display: Locator
+    """
+    Playwright `Locator` of the file display.
+    """
     loc_progress: Locator
+    """
+    Playwright `Locator` of the progress bar.
+    """
 
     # id: str,
     # label: TagChild,
@@ -1343,6 +2091,16 @@ def __init__(
         page: Page,
         id: str,
     ) -> None:
+        """
+        Initialize the InputFile.
+
+        Parameters
+        ----------
+        page
+            Playwright `Page` of the Shiny app.
+        id
+            The id of the file input.
+        """
         super().__init__(
             page,
             id=id,
@@ -1365,6 +2123,18 @@ def set(
         timeout: Timeout = None,
         expect_complete_timeout: Timeout = 30 * 1000,
     ) -> None:
+        """
+        Set the file upload.
+
+        Parameters
+        ----------
+        file_path
+            The path to the file to upload.
+        timeout
+            The timeout for the action. Defaults to `None`.
+        expect_complete_timeout
+            The timeout for the expectation that the upload is complete. Defaults to `30 * 1000`.
+        """
         self.loc.wait_for(state="visible", timeout=timeout)
         self.loc.scroll_into_view_if_needed(timeout=timeout)
         self.loc.set_input_files(file_path, timeout=timeout)
@@ -1377,40 +2147,98 @@ def expect_complete(
         *,
         timeout: Timeout = None,
     ) -> None:
+        """
+        Expect the file upload to be complete.
+
+        Parameters
+        ----------
+        timeout
+            The timeout for the expectation. Defaults to `None`.
+        """
         expect_to_have_style(self.loc_progress, "width", "100%", timeout=timeout)
 
     # TODO-future; Test multiple file upload
-    def expect_multiple(self, multiple: bool, *, timeout: Timeout = None) -> None:
-        _expect_multiple(self.loc, multiple, timeout=timeout)
+    def expect_multiple(self, value: bool, *, timeout: Timeout = None) -> None:
+        """
+        Expect the `multiple` attribute to have a specific value.
+
+        Parameters
+        ----------
+        value
+            The expected value of the `multiple` attribute.
+        timeout
+            The timeout for the expectation. Defaults to `None`.
+        """
+        _expect_multiple(self.loc, value, timeout=timeout)
 
     def expect_accept(
         self,
-        accept: list[str] | AttrValue,
+        value: list[str] | AttrValue,
         *,
         timeout: Timeout = None,
     ) -> None:
-        if isinstance(accept, list):
-            accept = ",".join(accept)
-        expect_attribute_to_have_value(self.loc, "accept", accept, timeout=timeout)
+        """
+        Expect the `accept` attribute to have a specific value.
+
+        Parameters
+        ----------
+        value
+            The expected value of the `accept` attribute.
+        timeout
+            The timeout for the expectation. Defaults to `None`.
+        """
+        if isinstance(value, list):
+            value = ",".join(value)
+        expect_attribute_to_have_value(self.loc, "accept", value, timeout=timeout)
+
+    def expect_width(self, value: StyleValue, *, timeout: Timeout = None) -> None:
+        """
+        Expect the width of the input file to have a specific value.
 
-    def expect_width(self, width: StyleValue, *, timeout: Timeout = None) -> None:
-        expect_to_have_style(self.loc_container, "width", width, timeout=timeout)
+        Parameters
+        ----------
+        value
+            The expected value of the width.
+        timeout
+            The timeout for the expectation. Defaults to `None`.
+        """
+        expect_to_have_style(self.loc_container, "width", value, timeout=timeout)
 
     def expect_button_label(
         self,
-        button_label: PatternOrStr,
+        value: PatternOrStr,
         *,
         timeout: Timeout = None,
     ) -> None:
-        playwright_expect(self.loc_button).to_have_text(button_label, timeout=timeout)
+        """
+        Expect the button label to have a specific value.
+
+        Parameters
+        ----------
+        value
+            The expected value of the button label.
+        timeout
+            The timeout for the expectation. Defaults to `None`.
+        """
+        playwright_expect(self.loc_button).to_have_text(value, timeout=timeout)
 
     def expect_capture(
         self,
-        capture: Literal["environment", "user"] | None,
+        value: Literal["environment", "user"] | None,
         *,
         timeout: Timeout = None,
     ) -> None:
-        expect_attribute_to_have_value(self.loc, "capture", capture, timeout=timeout)
+        """
+        Expect the `capture` attribute to have a specific value.
+
+        Parameters
+        ----------
+        value
+            The expected value of the `capture` attribute.
+        timeout
+            The timeout for the expectation. Defaults to `None`.
+        """
+        expect_attribute_to_have_value(self.loc, "capture", value, timeout=timeout)
 
     def expect_placeholder(self, value: AttrValue, *, timeout: Timeout = None) -> None:
         expect_attribute_to_have_value(
@@ -1418,32 +2246,36 @@ def expect_placeholder(self, value: AttrValue, *, timeout: Timeout = None) -> No
         )
 
 
-class _InputSliderBase(_WidthLocM, _InputWithLabel):
-    # id: str,
-    # label: TagChild,
-    # min: SliderValueArg,
-    # max: SliderValueArg,
-    # value: Union[SliderValueArg, Iterable[SliderValueArg]],
-    # step: Optional[SliderStepArg] = None,
-    # ticks: bool = True,
-    # animate: Union[bool, AnimationOptions] = False,
-    # width: Optional[str] = None,
-    # sep: str = ",",
-    # pre: Optional[str] = None,
-    # post: Optional[str] = None,
-    # time_format: Optional[str] = None,
-    # timezone: Optional[str] = None,
-    # drag_range: bool = True,
+class _InputSliderBase(_WidthLocM, _UiWithLabel):
 
     loc_irs: Locator
+    """
+    Playwright `Locator` of the input slider.
+    """
     loc_irs_ticks: Locator
+    """
+    Playwright `Locator` of the input slider ticks.
+    """
     loc_play_pause: Locator
+    """
+    Playwright `Locator` of the play/pause button.
+    """
 
     def __init__(
         self,
         page: Page,
         id: str,
     ) -> None:
+        """
+        Initialize the InputSlider.
+
+        Parameters
+        ----------
+        page
+            Playwright `Page` of the Shiny app.
+        id
+            The id of the slider.
+        """
         super().__init__(
             page,
             id=id,
@@ -1461,6 +2293,16 @@ def expect_tick_labels(
         *,
         timeout: Timeout = None,
     ) -> None:
+        """
+        Expect the tick labels of the input slider.
+
+        Parameters
+        ----------
+        value
+            The expected tick labels.
+        timeout
+            The timeout for the expectation. Defaults to `None`.
+        """
         if value is None:
             playwright_expect(self.loc_irs_ticks).to_have_count(0)
             return
@@ -1468,6 +2310,16 @@ def expect_tick_labels(
         playwright_expect(self.loc_irs_ticks).to_have_text(value, timeout=timeout)
 
     def expect_animate(self, exists: bool, *, timeout: Timeout = None) -> None:
+        """
+        Expect the animate button to exist.
+
+        Parameters
+        ----------
+        exists
+            Whether the animate button should exist.
+        timeout
+            The timeout for the expectation. Defaults to `None`.
+        """
         animate_count = 1 if exists else 0
         playwright_expect(self.loc_play_pause).to_have_count(animate_count)
 
@@ -1503,6 +2355,14 @@ def expect_animate_options(
     # become `play` over and over again. Instead, have explicit `play` and `pause`
     # methods.
     def click_play(self, *, timeout: Timeout = None) -> None:
+        """
+        Click the play button.
+
+        Parameters
+        ----------
+        timeout
+            The timeout for the action. Defaults to `None`.
+        """
         self.loc_container.wait_for(state="visible", timeout=timeout)
         self.loc_container.scroll_into_view_if_needed(timeout=timeout)
         _expect_class_value(
@@ -1511,6 +2371,14 @@ def click_play(self, *, timeout: Timeout = None) -> None:
         self.loc_play_pause.click()
 
     def click_pause(self, *, timeout: Timeout = None) -> None:
+        """
+        Click the pause button.
+
+        Parameters
+        ----------
+        timeout
+            The timeout for the action. Defaults to `None`.
+        """
         self.loc_container.wait_for(state="visible", timeout=timeout)
         self.loc_container.scroll_into_view_if_needed(timeout=timeout)
         _expect_class_value(
@@ -1519,36 +2387,106 @@ def click_pause(self, *, timeout: Timeout = None) -> None:
         self.loc_play_pause.click()
 
     def expect_min(self, value: AttrValue, *, timeout: Timeout = None) -> None:
+        """
+        Expect the input element to have the expected `min` attribute value.
+
+        Parameters
+        ----------
+        value
+            The expected value.
+        timeout
+            The timeout for the expectation. Defaults to `None`.
+        """
         expect_attribute_to_have_value(
             self.loc, "data-min", value=value, timeout=timeout
         )
 
     def expect_max(self, value: AttrValue, *, timeout: Timeout = None) -> None:
+        """
+        Expect the input element to have the expected `max` attribute value.
+
+        Parameters
+        ----------
+        value
+            The expected value.
+        timeout
+            The timeout for the expectation. Defaults to `None`.
+        """
         expect_attribute_to_have_value(
             self.loc, "data-max", value=value, timeout=timeout
         )
 
     def expect_step(self, value: AttrValue, *, timeout: Timeout = None) -> None:
+        """
+        Expect the input element to have the expected `step` attribute value.
+
+        Parameters
+        ----------
+        value
+            The expected value.
+        timeout
+            The timeout for the expectation. Defaults to `None`.
+        """
         expect_attribute_to_have_value(
             self.loc, "data-step", value=value, timeout=timeout
         )
 
     def expect_ticks(self, value: AttrValue, *, timeout: Timeout = None) -> None:
+        """
+        Expect the input element to have the expected `data-ticks` attribute value.
+
+        Parameters
+        ----------
+        value
+            The expected value.
+        timeout
+            The timeout for the expectation. Defaults to `None`.
+        """
         expect_attribute_to_have_value(
             self.loc, "data-grid", value=value, timeout=timeout
         )
 
     def expect_sep(self, value: AttrValue, *, timeout: Timeout = None) -> None:
+        """
+        Expect the input element to have the expected `data-sep` attribute value.
+
+        Parameters
+        ----------
+        value
+            The expected value.
+        timeout
+            The timeout for the expectation. Defaults to `None`.
+        """
         expect_attribute_to_have_value(
             self.loc, "data-prettify-separator", value=value, timeout=timeout
         )
 
     def expect_pre(self, value: AttrValue, *, timeout: Timeout = None) -> None:
+        """
+        Expect the input element to have the expected `data-pre` attribute value.
+
+        Parameters
+        ----------
+        value
+            The expected value.
+        timeout
+            The timeout for the expectation. Defaults to `None`.
+        """
         expect_attribute_to_have_value(
             self.loc, "data-prefix", value=value, timeout=timeout
         )
 
     def expect_post(self, value: AttrValue, *, timeout: Timeout = None) -> None:
+        """
+        Expect the input element to have the expected `data-post` attribute value.
+
+        Parameters
+        ----------
+        value
+            The expected value.
+        timeout
+            The timeout for the expectation. Defaults to `None`.
+        """
         expect_attribute_to_have_value(
             self.loc, "data-postfix", value=value, timeout=timeout
         )
@@ -1559,16 +2497,46 @@ def expect_post(self, value: AttrValue, *, timeout: Timeout = None) -> None:
     #     expect_attr(self.loc, "data-data-type", value=value, timeout=timeout)
 
     def expect_time_format(self, value: AttrValue, *, timeout: Timeout = None) -> None:
+        """
+        Asserts that the input element has the expected `data-time-format` attribute value.
+
+        Parameters
+        ----------
+        value
+            The expected value.
+        timeout
+            The maximum time to wait for the value to appear. Defaults to `None`.
+        """
         expect_attribute_to_have_value(
             self.loc, "data-time-format", value=value, timeout=timeout
         )
 
     def expect_timezone(self, value: AttrValue, *, timeout: Timeout = None) -> None:
+        """
+        Asserts that the input element has the expected `data-timezone` attribute value.
+
+        Parameters
+        ----------
+        value
+            The expected value.
+        timeout
+            The maximum time to wait for the value to appear. Defaults to `None`.
+        """
         expect_attribute_to_have_value(
             self.loc, "data-timezone", value=value, timeout=timeout
         )
 
     def expect_drag_range(self, value: AttrValue, *, timeout: Timeout = None) -> None:
+        """
+        Asserts that the input element has the expected `data-drag-range` attribute value.
+
+        Parameters
+        ----------
+        value
+            The expected value.
+        timeout
+            The maximum time to wait for the value to appear. Defaults to `None`.
+        """
         expect_attribute_to_have_value(
             self.loc, "data-drag-interval", value=value, timeout=timeout
         )
@@ -1617,6 +2585,18 @@ def should_continue(cur_pxls: float) -> bool:
         sleep_time = 0.05
 
         def slow_move(x: float, y: float, delay: float = sleep_time) -> None:
+            """
+            Slowly move the mouse to the given coordinates.
+
+            Parameters
+            ----------
+            x
+                The x-coordinate.
+            y
+                The y-coordinate.
+            delay
+                The delay between each move. Defaults to `sleep_time`.
+            """
             mouse.move(x, y)
             time.sleep(delay)
 
@@ -1685,17 +2665,42 @@ def _handle_center(
 
 
 class InputSlider(_InputSliderBase):
+    """Input slider control for :func:`~shiny.ui.input_slider`."""
+
     loc_irs_label: Locator
+    """
+    Playwright `Locator` of the input slider label.
+    """
 
     def __init__(
         self,
         page: Page,
         id: str,
     ) -> None:
+        """
+        Initialize the InputSlider object.
+
+        Parameters
+        ----------
+        page
+            The Playwright Page object.
+        id
+            The id of the input element.
+        """
         super().__init__(page, id=id)
         self.loc_irs_label = self.loc_irs.locator("> .irs > .irs-single")
 
     def expect_value(self, value: PatternOrStr, *, timeout: Timeout = None) -> None:
+        """
+        Asserts that the input element has the expected value.
+
+        Parameters
+        ----------
+        value
+            The expected value.
+        timeout
+            The maximum time to wait for the value to appear. Defaults to `None`.
+        """
         playwright_expect(self.loc_irs_label).to_have_text(value, timeout=timeout)
 
     def set(
@@ -1705,6 +2710,18 @@ def set(
         max_err_values: int = 15,
         timeout: Timeout = None,
     ) -> None:
+        """
+        Set the value of the slider.
+
+        Parameters
+        ----------
+        value
+            The value to set the slider to.
+        max_err_values
+            The maximum number of error values to display if the value is not found. Defaults to 15.
+        timeout
+            The maximum time to wait for the value to appear. Defaults to `None`.
+        """
         self._wait_for_container(timeout=timeout)
 
         handle = self.loc_irs.locator("> .irs-handle")
@@ -1723,14 +2740,32 @@ def set(
 
 
 class InputSliderRange(_InputSliderBase):
+    """Input slider range control for :func:`~shiny.ui.input_slider_range`."""
+
     loc_irs_label_from: Locator
+    """
+    Playwright `Locator` of the input slider label for the `from` handle.
+    """
     loc_irs_label_to: Locator
+    """
+    Playwright `Locator` of the input slider label for the `to` handle.
+    """
 
     def __init__(
         self,
         page: Page,
         id: str,
     ) -> None:
+        """
+        Initialize the InputSliderRange object.
+
+        Parameters
+        ----------
+        page
+            The Playwright Page object.
+        id
+            The id of the input element.
+        """
         super().__init__(page, id=id)
         self.loc_irs_label_from = self.loc_irs.locator("> .irs > .irs-from")
         self.loc_irs_label_to = self.loc_irs.locator("> .irs > .irs-to")
@@ -1745,6 +2780,16 @@ def expect_value(
         *,
         timeout: Timeout = None,
     ) -> None:
+        """
+        Asserts that the input element has the expected value.
+
+        Parameters
+        ----------
+        value
+            The expected value.
+        timeout
+            The maximum time to wait for the value to appear. Defaults to `None`.
+        """
         if all_missing(*value):
             raise ValueError("Both `value` tuple entries cannot be `MISSING_TYPE`")
         from_val = value[0]
@@ -1793,6 +2838,18 @@ def set(
         max_err_values: int = 15,
         timeout: Timeout = None,
     ) -> None:
+        """
+        Set the value of the slider.
+
+        Parameters
+        ----------
+        value
+            The value to set the slider to.
+        max_err_values
+            The maximum number of error values to display if the value is not found. Defaults to 15.
+        timeout
+            The maximum time to wait for the value to appear. Defaults to `None`.
+        """
         if all_missing(*value):
             raise ValueError("Both `value` tuple entries cannot be `MISSING_TYPE`")
 
@@ -1850,21 +2907,8 @@ def set(
 class _DateBase(
     _SetTextM,
     _WidthContainerM,
-    _InputWithLabel,
+    _UiWithLabel,
 ):
-    # id: str,
-    # label: TagChild,
-    # value: Optional[Union[date, str]] = None,
-    # min: Optional[Union[date, str]] = None,
-    # max: Optional[Union[date, str]] = None,
-    # format: str = "yyyy-mm-dd",
-    # startview: str = "month",
-    # weekstart: int = 0,
-    # language: str = "en",
-    # width: Optional[str] = None,
-    # autoclose: bool = True,
-    # datesdisabled: Optional[list[str]] = None,
-    # daysofweekdisabled: Optional[list[int]] = None,
 
     # Due to the `language` parameter, we can't use `datetime.date` as a value type
 
@@ -1874,6 +2918,16 @@ def expect_value(
         *,
         timeout: Timeout = None,
     ) -> None:
+        """
+        Asserts that the input element has the expected value.
+
+        Parameters
+        ----------
+        value
+            The expected value.
+        timeout
+            The maximum time to wait for the value to appear. Defaults to `None`.
+        """
         # if value is None:
         #     self.expect.to_be_empty(timeout=timeout)
         # else:
@@ -1885,6 +2939,16 @@ def expect_min_date(
         *,
         timeout: Timeout = None,
     ) -> None:
+        """
+        Asserts that the input element has the expected `data-min-date` attribute value.
+
+        Parameters
+        ----------
+        value
+            The expected `data-min-date` attribute value.
+        timeout
+            The maximum time to wait for the value to appear. Defaults to `None`.
+        """
         expect_attribute_to_have_value(
             self.loc, "data-min-date", value=value, timeout=timeout
         )
@@ -1895,6 +2959,16 @@ def expect_max_date(
         *,
         timeout: Timeout = None,
     ) -> None:
+        """
+        Asserts that the input element has the expected `data-max-date` attribute value.
+
+        Parameters
+        ----------
+        value
+            The expected `data-max-date` attribute value.
+        timeout
+            The maximum time to wait for the value to appear. Defaults to `None`.
+        """
         expect_attribute_to_have_value(
             self.loc, "data-max-date", value=value, timeout=timeout
         )
@@ -1905,6 +2979,16 @@ def expect_format(
         *,
         timeout: Timeout = None,
     ) -> None:
+        """
+        Asserts that the input element has the expected `data-date-format` attribute value.
+
+        Parameters
+        ----------
+        value
+            The expected `data-date-format` attribute value.
+        timeout
+            The maximum time to wait for the value to appear. Defaults to `None`.
+        """
         expect_attribute_to_have_value(
             self.loc, "data-date-format", value=value, timeout=timeout
         )
@@ -1915,6 +2999,16 @@ def expect_startview(
         *,
         timeout: Timeout = None,
     ) -> None:
+        """
+        Asserts that the input element has the expected `data-date-start-view` attribute value.
+
+        Parameters
+        ----------
+        value
+            The expected `data-date-start-view` attribute value.
+        timeout
+            The maximum time to wait for the value to appear. Defaults to `None`.
+        """
         expect_attribute_to_have_value(
             self.loc, "data-date-start-view", value=value, timeout=timeout
         )
@@ -1925,6 +3019,16 @@ def expect_weekstart(
         *,
         timeout: Timeout = None,
     ) -> None:
+        """
+        Asserts that the input element has the expected `data-date-week-start` attribute value.
+
+        Parameters
+        ----------
+        value
+            The expected `data-date-week-start` attribute value.
+        timeout
+            The maximum time to wait for the value to appear. Defaults to `None`.
+        """
         if isinstance(value, int):
             value = str(value)
         expect_attribute_to_have_value(
@@ -1937,6 +3041,16 @@ def expect_language(
         *,
         timeout: Timeout = None,
     ) -> None:
+        """
+        Asserts that the input element has the expected `data-date-language` attribute value.
+
+        Parameters
+        ----------
+        value
+            The expected `data-date-language` attribute value.
+        timeout
+            The maximum time to wait for the value to appear. Defaults to `None`.
+        """
         expect_attribute_to_have_value(
             self.loc, "data-date-language", value=value, timeout=timeout
         )
@@ -1948,6 +3062,16 @@ def expect_autoclose(
         *,
         timeout: Timeout = None,
     ) -> None:
+        """
+        Asserts that the input element has the expected `data-date-autoclose` attribute value.
+
+        Parameters
+        ----------
+        value
+            The expected `data-date-autoclose` attribute value.
+        timeout
+            The maximum time to wait for the value to appear. Defaults to `None`.
+        """
         expect_attribute_to_have_value(
             self.loc, "data-date-autoclose", value=value, timeout=timeout
         )
@@ -1958,6 +3082,16 @@ def expect_datesdisabled(
         *,
         timeout: Timeout = None,
     ) -> None:
+        """
+        Asserts that the input element has the expected `data-date-dates-disabled` attribute value.
+
+        Parameters
+        ----------
+        value
+            The expected `data-date-dates-disabled` attribute value.
+        timeout
+            The maximum time to wait for the value to appear. Defaults to `None`.
+        """
         if isinstance(value, list):
             assert len(value) > 0, "`value` must be `None` or a non-empty list"
         value_str = "null" if value is None else json.dumps(value)
@@ -1974,6 +3108,16 @@ def expect_daysofweekdisabled(
         *,
         timeout: Timeout = None,
     ) -> None:
+        """
+        Asserts that the input element has the expected `data-date-days-of-week-disabled` attribute value.
+
+        Parameters
+        ----------
+        value
+            The expected `data-date-days-of-week-disabled` attribute value.
+        timeout
+            The maximum time to wait for the value to appear. Defaults to `None`.
+        """
         if isinstance(value, list):
             assert len(value) > 0, "`value` must be `None` or a non-empty list"
         value_str = "null" if value is None else json.dumps(value)
@@ -1987,6 +3131,16 @@ def expect_daysofweekdisabled(
 
 class InputDate(_DateBase):
     def __init__(self, page: Page, id: str) -> None:
+        """
+        Initialize an InputDate object.
+
+        Parameters
+        ----------
+        page
+            The page object.
+        id
+            The id of the input element.
+        """
         super().__init__(
             page,
             id=id,
@@ -1995,29 +3149,41 @@ def __init__(self, page: Page, id: str) -> None:
         )
 
 
-class InputDateRange(_WidthContainerM, _InputWithLabel):
-    # id: str,
-    # label: TagChild,
-    # *,
-    # start: Optional[Union[date, str]] = None,
-    # end: Optional[Union[date, str]] = None,
-    # min: Optional[Union[date, str]] = None,
-    # max: Optional[Union[date, str]] = None,
-    # format: str = "yyyy-mm-dd",
-    # startview: str = "month",
-    # weekstart: int = 0,
-    # language: str = "en",
-    # separator: str = " to ",
-    # width: Optional[str] = None,
-    # autoclose: bool = True,
+class InputDateRange(_WidthContainerM, _UiWithLabel):
+    """Input date range control for :func:`~shiny.ui.input_date_range`."""
 
     loc_separator: Locator
+    """
+    Playwright `Locator` of the separator between the two input elements.
+    """
     loc_start: Locator
+    """
+    Playwright `Locator` of the start date input element.
+    """
     loc_end: Locator
+    """
+    Playwright `Locator` of the end date input element.
+    """
     date_start: _DateBase
+    """
+    The start date input element.
+    """
     date_end: _DateBase
+    """
+    The end date input element.
+    """
 
     def __init__(self, page: Page, id: str) -> None:
+        """
+        Initialize an InputDateRange object.
+
+        Parameters
+        ----------
+        page
+            The page object.
+        id
+            The id of the input element.
+        """
         super().__init__(
             page,
             id=id,
@@ -2051,6 +3217,16 @@ def set(
         *,
         timeout: Timeout = None,
     ) -> None:
+        """
+        Sets the value of the input element.
+
+        Parameters
+        ----------
+        value
+            The value to set. The first element is the start date and the second element is the end date.
+        timeout
+            The maximum time to wait for the value to be set. Defaults to `None`.
+        """
         start = value[0]
         end = value[1]
         # TODO-future; Composable set() methods?
@@ -2069,6 +3245,16 @@ def expect_value(
         *,
         timeout: Timeout = None,
     ) -> None:
+        """
+        Asserts that the input element has the expected value.
+
+        Parameters
+        ----------
+        value
+            The expected value. The first element is the start date and the second element is the end date.
+        timeout
+            The maximum time to wait for the value to appear. Defaults to `None`.
+        """
         if all_missing(*value):
             raise ValueError("Both `start_val` and `end_val` can not be `MISSING_TYPE`")
         start_val = value[0]
@@ -2089,6 +3275,16 @@ def expect_min_date(
         *,
         timeout: Timeout = None,
     ) -> None:
+        """
+        Asserts that the input element has the expected minimum date.
+
+        Parameters
+        ----------
+        value
+            The expected minimum date.
+        timeout
+            The maximum time to wait for the minimum date to appear. Defaults to `None`.
+        """
         # TODO-future; Composable expectations
         self.date_start.expect_min_date(value, timeout=timeout)
         self.date_end.expect_min_date(value, timeout=timeout)
@@ -2100,6 +3296,16 @@ def expect_max_date(
         *,
         timeout: Timeout = None,
     ) -> None:
+        """
+        Asserts that the input element has the expected maximum date.
+
+        Parameters
+        ----------
+        value
+            The expected maximum date.
+        timeout
+            The maximum time to wait for the maximum date to appear. Defaults to `None`.
+        """
         # TODO-future; Composable expectations
         self.date_start.expect_max_date(value, timeout=timeout)
         self.date_end.expect_max_date(value, timeout=timeout)
@@ -2111,6 +3317,16 @@ def expect_format(
         *,
         timeout: Timeout = None,
     ) -> None:
+        """
+        Asserts that the input element has the expected format.
+
+        Parameters
+        ----------
+        value
+            The expected format.
+        timeout
+            The maximum time to wait for the format to appear. Defaults to `None`.
+        """
         # TODO-future; Composable expectations
         self.date_start.expect_format(value, timeout=timeout)
         self.date_end.expect_format(value, timeout=timeout)
@@ -2122,6 +3338,16 @@ def expect_startview(
         *,
         timeout: Timeout = None,
     ) -> None:
+        """
+        Asserts that the input element has the expected start view.
+
+        Parameters
+        ----------
+        value
+            The expected start view.
+        timeout
+            The maximum time to wait for the start view to appear. Defaults to `None`.
+        """
         # TODO-future; Composable expectations
         self.date_start.expect_startview(value, timeout=timeout)
         self.date_end.expect_startview(value, timeout=timeout)
@@ -2133,6 +3359,16 @@ def expect_weekstart(
         *,
         timeout: Timeout = None,
     ) -> None:
+        """
+        Asserts that the input element has the expected week start.
+
+        Parameters
+        ----------
+        value
+            The expected week start.
+        timeout
+            The maximum time to wait for the week start to appear. Defaults to `None`.
+        """
         # TODO-future; Composable expectations
         self.date_start.expect_weekstart(value, timeout=timeout)
         self.date_end.expect_weekstart(value, timeout=timeout)
@@ -2144,6 +3380,16 @@ def expect_language(
         *,
         timeout: Timeout = None,
     ) -> None:
+        """
+        Asserts that the input element has the expected language.
+
+        Parameters
+        ----------
+        value
+            The expected language.
+        timeout
+            The maximum time to wait for the language to appear. Defaults to `None`.
+        """
         # TODO-future; Composable expectations
         self.date_start.expect_language(value, timeout=timeout)
         self.date_end.expect_language(value, timeout=timeout)
@@ -2155,6 +3401,16 @@ def expect_separator(
         *,
         timeout: Timeout = None,
     ) -> None:
+        """
+        Asserts that the input element has the expected separator.
+
+        Parameters
+        ----------
+        value
+            The expected separator.
+        timeout
+            The maximum time to wait for the separator to appear. Defaults to `None`.
+        """
         playwright_expect(self.loc_separator).to_have_text(value, timeout=timeout)
 
     # width: Optional[str] = None,
@@ -2166,6 +3422,16 @@ def expect_autoclose(
         *,
         timeout: Timeout = None,
     ) -> None:
+        """
+        Asserts that the input element has the expected autoclose value.
+
+        Parameters
+        ----------
+        value
+            The expected autoclose value.
+        timeout
+            The maximum time to wait for the value to appear. Defaults to `None`.
+        """
         # TODO-future; Composable expectations
         self.date_start.expect_autoclose(value, timeout=timeout)
         self.date_end.expect_autoclose(value, timeout=timeout)
@@ -2183,9 +3449,22 @@ class _OutputBaseP(Protocol):
 
 
 class _OutputBase:
+    """
+    Base class for output controls.
+    """
+
     id: str
+    """
+    The ID of the output control.
+    """
     loc: Locator
+    """
+    Playwright `Locator` of the output control.
+    """
     page: Page
+    """
+    Playwright `Page` of the Shiny app.
+    """
 
     def __init__(
         self,
@@ -2217,6 +3496,16 @@ def expect_value(
         *,
         timeout: Timeout = None,
     ) -> None:
+        """
+        Asserts that the output has the expected value.
+
+        Parameters
+        ----------
+        value
+            The expected value.
+        timeout
+            The maximum time to wait for the value to appear. Defaults to `None`.
+        """
         """Note this function will trim value and output text value before comparing them"""
         self.expect.to_have_text(value, timeout=timeout)
 
@@ -2224,7 +3513,7 @@ def expect_value(
 class _OutputContainerP(_OutputBaseP, Protocol):
     def expect_container_tag(
         self: _OutputBaseP,
-        tag_name: Literal["span", "div"] | str,
+        value: Literal["span", "div"] | str,
         *,
         timeout: Timeout = None,
     ) -> None: ...
@@ -2233,73 +3522,195 @@ def expect_container_tag(
 class _OutputContainerM:
     def expect_container_tag(
         self: _OutputBaseP,
-        tag_name: Literal["span", "div"] | str,
+        value: Literal["span", "div"] | str,
         *,
         timeout: Timeout = None,
     ) -> None:
-        loc = self.loc.locator(f"xpath=self::{tag_name}")
+        """
+        Asserts that the output has the expected container tag.
+
+        Parameters
+        ----------
+        value
+            The expected container tag.
+        timeout
+            The maximum time to wait for the container tag to appear. Defaults to `None`.
+        """
+        loc = self.loc.locator(f"xpath=self::{value}")
         playwright_expect(loc).to_have_count(1, timeout=timeout)
 
 
 class _OutputInlineContainerM(_OutputContainerM):
     def expect_inline(
-        self: _OutputContainerP, inline: bool = False, *, timeout: Timeout = None
+        self: _OutputContainerP,
+        value: bool = False,
+        *,
+        timeout: Timeout = None,
     ) -> None:
-        tag_name = "span" if inline else "div"
+        """
+        Asserts that the output is inline.
+
+        Parameters
+        ----------
+        value
+            Whether the output is inline.
+        timeout
+            The maximum time to wait for the output to appear. Defaults to `None`.
+        """
+        tag_name = "span" if value else "div"
         self.expect_container_tag(tag_name, timeout=timeout)
 
 
-class OutputText(_OutputInlineContainerM, _OutputTextValue):
+class OutputText(
+    _OutputInlineContainerM,
+    _OutputTextValue,
+):
+    """Text output control for :func:`~shiny.ui.text_output`."""
+
+    loc: Locator
+    """
+    Playwright `Locator` of the text output.
+    """
+
     def __init__(
         self,
         page: Page,
         id: str,
     ) -> None:
+        """
+        Initializes a text output.
+
+        Parameters
+        ----------
+        page
+            Playwright `Page` of the Shiny app.
+        id
+            The ID of the text output.
+        """
         super().__init__(page, id=id, loc=f"#{id}.shiny-text-output")
 
     def get_value(self, *, timeout: Timeout = None) -> str:
+        """
+        Gets the text value of the output.
+
+        Parameters
+        ----------
+        timeout
+            The maximum time to wait for the value to appear. Defaults to `None`.
+        """
         return self.loc.inner_text(timeout=timeout)
 
 
 class OutputCode(_OutputTextValue):
+    """Code output control for :func:`~shiny.ui.code_output`."""
+
+    loc: Locator
+    """
+    Playwright `Locator` of the code output.
+    """
+
     def __init__(self, page: Page, id: str) -> None:
+        """
+        Initializes a code output.
+
+        Parameters
+        ----------
+        page
+            Playwright `Page` of the Shiny app.
+        id
+            The ID of the code output.
+        """
         super().__init__(page, id=id, loc=f"pre#{id}.shiny-text-output")
 
     def expect_has_placeholder(
-        self, placeholder: bool = False, *, timeout: Timeout = None
+        self,
+        value: bool = False,
+        *,
+        timeout: Timeout = None,
     ) -> None:
+        """
+        Asserts that the code output has the expected placeholder.
+
+        Parameters
+        ----------
+        value
+            Whether the code output has a placeholder.
+        timeout
+            The maximum time to wait for the placeholder to appear. Defaults to `None`.
+        """
         _expect_class_value(
             self.loc,
             cls="noplaceholder",
-            has_class=not placeholder,
+            has_class=not value,
             timeout=timeout,
         )
 
 
 class OutputTextVerbatim(_OutputTextValue):
+    """Verbatim text output control for :func:`~shiny.ui.text_output_verbatim`."""
+
+    loc: Locator
+    """
+    Playwright `Locator` of the verbatim text output.
+    """
+
     def __init__(self, page: Page, id: str) -> None:
+        """
+        Initializes a verbatim text output.
+
+        Parameters
+        ----------
+        page
+            Playwright `Page` of the Shiny app.
+        id
+            The ID of the verbatim text output.
+        """
         super().__init__(page, id=id, loc=f"pre#{id}.shiny-text-output")
 
     def expect_has_placeholder(
-        self, placeholder: bool = False, *, timeout: Timeout = None
+        self,
+        value: bool = False,
+        *,
+        timeout: Timeout = None,
     ) -> None:
+        """
+        Asserts that the verbatim text output has the expected placeholder.
+
+        Parameters
+        ----------
+        value
+            Whether the verbatim text output has a placeholder.
+        timeout
+            The maximum time to wait for the placeholder to appear. Defaults to `None`.
+        """
         _expect_class_value(
             self.loc,
             cls="noplaceholder",
-            has_class=not placeholder,
+            has_class=not value,
             timeout=timeout,
         )
 
 
 class _OutputImageBase(_OutputInlineContainerM, _OutputBase):
-    # id: str
-    # width: str = "100%"
-    # height: str = "400px"
-    # inline: bool = False
 
     loc_img: Locator
+    """
+    Playwright `Locator` of the image.
+    """
 
     def __init__(self, page: Page, id: str, loc_classes: str = "") -> None:
+        """
+        Initializes an image output.
+
+        Parameters
+        ----------
+        page
+            Playwright `Page` of the Shiny app.
+        id
+            The ID of the image.
+        loc_classes
+            Additional classes to locate the image. Defaults to "".
+        """
         super().__init__(
             page,
             id=id,
@@ -2313,6 +3724,16 @@ def expect_height(
         *,
         timeout: Timeout = None,
     ) -> None:
+        """
+        Asserts that the image has the expected height.
+
+        Parameters
+        ----------
+        value
+            The expected height.
+        timeout
+            The maximum time to wait for the height to appear. Defaults to `None`.
+        """
         expect_to_have_style(self.loc, "height", value, timeout=timeout)
 
     def expect_width(
@@ -2321,6 +3742,16 @@ def expect_width(
         *,
         timeout: Timeout = None,
     ) -> None:
+        """
+        Asserts that the image has the expected width.
+
+        Parameters
+        ----------
+        value
+            The expected width.
+        timeout
+            The maximum time to wait for the width to appear. Defaults to `None`.
+        """
         expect_to_have_style(self.loc, "width", value, timeout=timeout)
 
     def expect_img_src(
@@ -2329,6 +3760,16 @@ def expect_img_src(
         *,
         timeout: Timeout = None,
     ) -> None:
+        """
+        Asserts that the image has the expected src.
+
+        Parameters
+        ----------
+        value
+            The expected src.
+        timeout
+            The maximum time to wait for the src to appear. Defaults to `None`.
+        """
         expect_attribute_to_have_value(self.loc_img, "src", value, timeout=timeout)
 
     def expect_img_width(
@@ -2337,6 +3778,16 @@ def expect_img_width(
         *,
         timeout: Timeout = None,
     ) -> None:
+        """
+        Asserts that the image has the expected width.
+
+        Parameters
+        ----------
+        value
+            The expected width.
+        timeout
+            The maximum time to wait for the width to appear. Defaults to `None`.
+        """
         expect_attribute_to_have_value(self.loc_img, "width", value, timeout=timeout)
 
     def expect_img_height(
@@ -2345,6 +3796,16 @@ def expect_img_height(
         *,
         timeout: Timeout = None,
     ) -> None:
+        """
+        Asserts that the image has the expected height.
+
+        Parameters
+        ----------
+        value
+            The expected height.
+        timeout
+            The maximum time to wait for the height to appear. Defaults to `None`.
+        """
         expect_attribute_to_have_value(self.loc_img, "height", value, timeout=timeout)
 
     def expect_img_alt(
@@ -2353,6 +3814,16 @@ def expect_img_alt(
         *,
         timeout: Timeout = None,
     ) -> None:
+        """
+        Asserts that the image has the expected alt text.
+
+        Parameters
+        ----------
+        value
+            The expected alt text.
+        timeout
+            The maximum time to wait for the alt text to appear. Defaults to `None`.
+        """
         expect_attribute_to_have_value(self.loc_img, "alt", value, timeout=timeout)
 
     # def expect_img_style(
@@ -2366,135 +3837,272 @@ def expect_img_alt(
 
 class OutputImage(_OutputImageBase):
     def __init__(self, page: Page, id: str) -> None:
+        """
+        Initializes an image output.
+
+        Parameters
+        ----------
+        page
+            Playwright `Page` of the Shiny app.
+        id
+            The ID of the image.
+        """
         super().__init__(page, id=id)
 
 
 class OutputPlot(_OutputImageBase):
-    # shiny-plot-output
-    # id: str
-    # width: str = "100%"
-    # height: str = "400px"
-    # inline: bool = False
+    """Plot output control for :func:`~shiny.ui.plot_output`."""
+
+    loc: Locator
+    """
+    Playwright `Locator` of the plot output.
+    """
+
     def __init__(self, page: Page, id: str) -> None:
+        """
+        Initializes a plot output.
+
+        Parameters
+        ----------
+        page
+            Playwright `Page` of the Shiny app.
+        id
+            The ID of the plot.
+        """
         super().__init__(page, id=id, loc_classes=".shiny-plot-output")
 
 
 class OutputUi(_OutputInlineContainerM, _OutputBase):
-    # id: str,
-    # inline: bool = False,
-    # container: Optional[TagFunction] = None,
+    """UI output control for :func:`~shiny.ui.ui_output`."""
+
     def __init__(self, page: Page, id: str) -> None:
+        """
+        Initializes a UI output.
+
+        Parameters
+        ----------
+        page
+            Playwright `Page` of the Shiny app.
+        id
+            The ID of the UI output.
+        """
         super().__init__(page, id=id, loc=f"#{id}")
 
     # TODO-future; Should we try verify that `recalculating` class is not present? Do this for all outputs!
-    def expect_empty(self, empty: bool, *, timeout: Timeout = None) -> None:
-        if empty:
+    def expect_empty(self, value: bool, *, timeout: Timeout = None) -> None:
+        """
+        Asserts that the output is empty.
+
+        Parameters
+        ----------
+        value
+            Whether the output is empty.
+        timeout
+            The maximum time to wait for the output to be empty. Defaults to `None`.
+        """
+        if value:
             self.expect.to_be_empty(timeout=timeout)
         else:
             self.expect.not_to_be_empty(timeout=timeout)
 
-    def expect_text(self, text: str, *, timeout: Timeout = None) -> None:
-        self.expect.to_have_text(text, timeout=timeout)
+    def expect_text(self, value: str, *, timeout: Timeout = None) -> None:
+        """
+        Asserts that the output has the expected text.
+
+        Parameters
+        ----------
+        value
+            The expected text.
+        timeout
+            The maximum time to wait for the text to appear. Defaults to `None`.
+        """
+
+        self.expect.to_have_text(value, timeout=timeout)
 
 
 # When making selectors, use `xpath` so that direct decendents can be checked
 class OutputTable(_OutputBase):
-    # id: str,
-    # **kwargs: TagAttrArg
+    """Table output control for :func:`~shiny.ui.table_output`."""
+
     def __init__(self, page: Page, id: str) -> None:
+        """
+        Initializes a table output.
+
+        Parameters
+        ----------
+        page
+            Playwright `Page` of the Shiny app.
+        id
+            The ID of the table.
+        """
         super().__init__(page, id=id, loc=f"#{id}")
 
     def expect_cell(
         self,
-        text: PatternOrStr,
+        value: PatternOrStr,
         row: int,
         col: int,
         *,
         timeout: Timeout = None,
     ) -> None:
+        """
+        Asserts that the table cell has the expected text.
+
+        Parameters
+        ----------
+        value
+            The expected text in the cell.
+        row
+            The row number.
+        col
+            The column number.
+        timeout
+            The maximum time to wait for the text to appear. Defaults to `None`.
+        """
         assert_type(row, int)
         assert_type(col, int)
         playwright_expect(
             self.loc.locator(
                 f"xpath=./table/tbody/tr[{row}]/td[{col}] | ./table/tbody/tr[{row}]/th[{col}]"
             )
-        ).to_have_text(text, timeout=timeout)
+        ).to_have_text(value, timeout=timeout)
 
     def expect_column_labels(
         self,
-        labels: ListPatternOrStr | None,
+        value: ListPatternOrStr | None,
         *,
         timeout: Timeout = None,
     ) -> None:
-        if isinstance(labels, list) and len(labels) == 0:
-            labels = None
+        """
+        Asserts that the table has the expected column labels.
+
+        Parameters
+        ----------
+        value
+            The expected column labels. If None, it asserts that the table has no column labels.
+        timeout
+            The maximum time to wait for the column labels to appear. Defaults to `None`.
+        """
+        if isinstance(value, list) and len(value) == 0:
+            value = None
 
-        if labels is None:
+        if value is None:
             playwright_expect(
                 self.loc.locator("xpath=./table/thead/tr/th")
             ).to_have_count(0, timeout=timeout)
         else:
             playwright_expect(
                 self.loc.locator("xpath=./table/thead/tr/th")
-            ).to_have_text(labels, timeout=timeout)
+            ).to_have_text(value, timeout=timeout)
 
     def expect_column_text(
         self,
         col: int,
         # Can't use `None` as we don't know how many rows exist
-        text: ListPatternOrStr,
+        value: ListPatternOrStr,
         *,
         timeout: Timeout = None,
     ) -> None:
+        """
+        Asserts that the column has the expected text.
+
+        Parameters
+        ----------
+        col
+            The column number.
+        value
+            The expected text in the column.
+        timeout
+            The maximum time to wait for the text to appear. Defaults to `None`.
+        """
         assert_type(col, int)
         playwright_expect(
             self.loc.locator(f"xpath=./table/tbody/tr/td[{col}]")
         ).to_have_text(
-            text,
+            value,
             timeout=timeout,
         )
 
     def expect_n_col(
         self,
-        n: int,
+        value: int,
         *,
         timeout: Timeout = None,
     ) -> None:
+        """
+        Asserts that the table has the expected number of columns.
+
+        Parameters
+        ----------
+        value
+            The expected number of columns in the table.
+        timeout
+            The maximum time to wait for the table to have the expected number of columns. Defaults to `None`.
+        """
         playwright_expect(
             # self.loc.locator("xpath=./table/thead/tr[1]/(td|th)")
             self.loc.locator("xpath=./table/thead/tr[1]/td | ./table/thead/tr[1]/th")
         ).to_have_count(
-            n,
+            value,
             timeout=timeout,
         )
 
     def expect_n_row(
         self,
-        n: int,
+        value: int,
         *,
         timeout: Timeout = None,
     ) -> None:
+        """
+        Asserts that the table has the expected number of rows.
+
+        Parameters
+        ----------
+        value
+            The expected number of rows in the table.
+        timeout
+            The maximum time to wait for the table to have the expected number of rows. Defaults to `None`.
+        """
         playwright_expect(self.loc.locator("xpath=./table/tbody/tr")).to_have_count(
-            n,
+            value,
             timeout=timeout,
         )
 
 
 class Sidebar(
     _WidthLocM,
-    _InputWithContainer,
+    _UiWithContainer,
 ):
-    # *args: TagChild | TagAttrs,
-    # width: CssUnit = 250,
-    # position: Literal["left", "right"] = "left",
-    # open: Literal["desktop", "open", "closed", "always"] = "desktop",
-    # id: Optional[str] = None,
-    # title: TagChild | str = None,
-    # bg: Optional[str] = None,
-    # fg: Optional[str] = None,
-    # class_: Optional[str] = None,  # TODO-future; Consider using `**kwargs` instead
-    # max_height_mobile: Optional[str | float] = None,
+    """Sidebar control for func: `~shiny.ui.sidebar`."""
+
+    loc_container: Locator
+    """
+    Playwright `Locator` for the sidebar layout.
+    """
+    loc: Locator
+    """
+    Playwright `Locator` for the sidebar.
+    """
+    loc_handle: Locator
+    """
+    Playwright `Locator` for the open/close handle of the sidebar.
+    """
+    loc_position: Locator
+    """
+    Playwright `Locator` for the position of the sidebar.
+    """
+
     def __init__(self, page: Page, id: str) -> None:
+        """
+        Initializes a sidebar control.
+
+        Parameters
+        ----------
+        page
+            Playwright `Page` of the Shiny app.
+        id
+            The ID of the sidebar.
+        """
         super().__init__(
             page,
             id=id,
@@ -2505,45 +4113,106 @@ def __init__(self, page: Page, id: str) -> None:
         self.loc_position = self.loc.locator("..")
 
     def expect_text(self, value: PatternOrStr, *, timeout: Timeout = None) -> None:
+        """
+        Asserts that the sidebar has the expected text.
+
+        Parameters
+        ----------
+        value
+            The expected text in the sidebar.
+        timeout
+            The maximum time to wait for the text to appear. Defaults to `None`.
+        """
         playwright_expect(self.loc).to_have_text(value, timeout=timeout)
 
     def expect_position(
-        self, position: Literal["left", "right"], *, timeout: Timeout = None
+        self,
+        value: Literal["left", "right"],
+        *,
+        timeout: Timeout = None,
     ) -> None:
-        is_right_sidebar = position == "right"
+        """
+        Asserts that the sidebar is in the expected position.
+
+        Parameters
+        ----------
+        value
+            The expected position of the sidebar.
+        timeout
+            The maximum time to wait for the sidebar to appear. Defaults to `None`.
+        """
+        is_right_sidebar = value == "right"
         _expect_class_value(
             self.loc_position,
-            f"sidebar-{position}",
+            f"sidebar-{value}",
             is_right_sidebar,
             timeout=timeout,
         )
 
     def expect_handle(self, exists: bool, *, timeout: Timeout = None) -> None:
+        """
+        Asserts that the sidebar handle exists or does not exist.
+
+        Parameters
+        ----------
+        exists
+            `True` if the sidebar open/close handle should exist, `False` otherwise.
+        timeout
+            The maximum time to wait for the sidebar handle to appear. Defaults to `None`.
+        """
         playwright_expect(self.loc_handle).to_have_count(int(exists), timeout=timeout)
 
-    def expect_open(self, open: bool, *, timeout: Timeout = None) -> None:
+    def expect_open(self, value: bool, *, timeout: Timeout = None) -> None:
+        """
+        Expect the sidebar to be open or closed.
+
+        Parameters
+        ----------
+        value
+            `True` if the sidebar should be open, `False` to be closed.
+        timeout
+            The maximum time to wait for the sidebar to open or close. Defaults to `None`.
+        """
         playwright_expect(self.loc_handle).to_have_attribute(
-            "aria-expanded", str(open).lower(), timeout=timeout
+            "aria-expanded", str(value).lower(), timeout=timeout
         )
 
     def set(self, open: bool, *, timeout: Timeout = None) -> None:
+        """
+        Sets the sidebar to be open or closed.
+
+        Parameters
+        ----------
+        open
+            `True` to open the sidebar and `False` to close it.
+        timeout
+            The maximum time to wait for the sidebar to open or close. Defaults to `None`.
+        """
         if open ^ (self.loc_handle.get_attribute("aria-expanded") == "true"):
             self.toggle(timeout=timeout)
 
     def toggle(self, *, timeout: Timeout = None) -> None:
+        """
+        Toggles the sidebar open or closed.
+
+        Parameters
+        ----------
+        timeout
+            The maximum time to wait for the sidebar to toggle. Defaults to `None`.
+        """
         self.loc_handle.wait_for(state="visible", timeout=timeout)
         self.loc_handle.scroll_into_view_if_needed(timeout=timeout)
         self.loc_handle.click(timeout=timeout)
 
 
-class _CardBodyP(_InputBaseP, Protocol):
+class _CardBodyP(_UiBaseP, Protocol):
     """
     Represents the body of a card control.
     """
 
     loc_body: Locator
     """
-    The locator for the body element of the card control.
+    Playwright `Locator` for the body element of the card control.
     """
 
 
@@ -2552,7 +4221,7 @@ class _CardBodyM:
 
     def expect_body(
         self: _CardBodyP,
-        text: PatternOrStr | list[PatternOrStr],
+        value: PatternOrStr | list[PatternOrStr],
         *,
         timeout: Timeout = None,
     ) -> None:
@@ -2563,22 +4232,22 @@ def expect_body(
         text
             The expected text or a list of expected texts.
         timeout
-            The maximum time to wait for the text to appear. Defaults to None.
+            The maximum time to wait for the text to appear. Defaults to `None`.
         """
         playwright_expect(self.loc).to_have_text(
-            text,
+            value,
             timeout=timeout,
         )
 
 
-class _CardFooterLayoutP(_InputBaseP, Protocol):
+class _CardFooterLayoutP(_UiBaseP, Protocol):
     """
     Represents the layout of the footer in a card.
     """
 
     loc_footer: Locator
     """
-    The locator for the footer element.
+    Playwright `Locator` for the footer element.
     """
 
 
@@ -2589,7 +4258,7 @@ class _CardFooterM:
 
     def expect_footer(
         self: _CardFooterLayoutP,
-        text: PatternOrStr,
+        value: PatternOrStr,
         *,
         timeout: Timeout = None,
     ) -> None:
@@ -2598,138 +4267,142 @@ def expect_footer(
 
         Parameters
         ----------
-        text
+        value
             The expected text in the footer section.
         timeout
-            The maximum time to wait for the footer text to appear. Defaults to None.
+            The maximum time to wait for the footer text to appear. Defaults to `None`.
         """
         playwright_expect(self.loc_footer).to_have_text(
-            text,
+            value,
             timeout=timeout,
         )
 
 
-class _CardFullScreenLayoutP(_OutputBaseP, Protocol):
+class _CardValueBoxFullScreenLayoutP(_OutputBaseP, Protocol):
     """
-    Represents a card full-screen layout for the Playwright controls.
+    Represents a card / Value Box full-screen layout for the Playwright controls.
     """
 
     loc_title: Locator
     """
-    The locator for the title element.
+    Playwright `Locator` for the title element.
     """
     _loc_fullscreen: Locator
     """
-    The locator for the full-screen element.
+    Playwright `Locator` for the full-screen element.
     """
     _loc_close_button: Locator
     """
-    The locator for the close button element.
+    Playwright `Locator` for the close button element.
     """
 
 
-class _CardFullScreenM:
+class _CardValueBoxFullScreenM:
     """
-    Represents a class for managing full screen functionality of a card.
+    Represents a class for managing full screen functionality of a Card or Value Box.
     """
 
+    # TODO-karan-test: Convert `open_full_screen` and `close_full_screen` to `set_full_screen(open:bool)`
     def open_full_screen(
-        self: _CardFullScreenLayoutP, *, timeout: Timeout = None
+        self: _CardValueBoxFullScreenLayoutP, *, timeout: Timeout = None
     ) -> None:
         """
-        Opens the card in full screen mode.
+        Opens the element in full screen mode.
 
         Parameters
         ----------
         timeout
-            The maximum time to wait for the card to open in full screen mode. Defaults to None.
+            The maximum time to wait for full screen mode to open. Defaults to `None`.
         """
         self.loc_title.hover(timeout=timeout)
         self._loc_fullscreen.wait_for(state="visible", timeout=timeout)
         self._loc_fullscreen.click(timeout=timeout)
 
     def close_full_screen(
-        self: _CardFullScreenLayoutP, *, timeout: Timeout = None
+        self: _CardValueBoxFullScreenLayoutP, *, timeout: Timeout = None
     ) -> None:
         """
-        Closes the card from full screen mode.
+        Exits full screen mode.
 
         Parameters
         ----------
         timeout
-            The maximum time to wait for the card to close from full screen mode. Defaults to None.
+            The maximum time to wait to wait for full screen mode to exit. Defaults to `None`.
         """
         self._loc_close_button.click(timeout=timeout)
 
-    def expect_full_screen_open(
-        self: _CardFullScreenLayoutP, open: bool, *, timeout: Timeout = None
+    def expect_full_screen(
+        self: _CardValueBoxFullScreenLayoutP, value: bool, *, timeout: Timeout = None
     ) -> None:
         """
-        Verifies if the card is expected to be in full screen mode.
+        Verifies if the full screen mode is currently open.
 
         Parameters
         ----------
-        open
-            True if the card is expected to be in full screen mode, False otherwise.
+        value
+            `True` if the item is to be in full screen mode, `False` otherwise.
         timeout
-            The maximum time to wait for the verification. Defaults to None.
+            The maximum time to wait for the verification. Defaults to `None`.
         """
         playwright_expect(self._loc_close_button).to_have_count(
-            int(open), timeout=timeout
+            int(value), timeout=timeout
         )
 
     def expect_full_screen_available(
-        self: _CardFullScreenLayoutP, available: bool, *, timeout: Timeout = None
+        self: _CardValueBoxFullScreenLayoutP,
+        value: bool,
+        *,
+        timeout: Timeout = None,
     ) -> None:
         """
-        Expects the card to be available for full screen mode.
+        Expects whether full screen mode is available for the element.
 
         Parameters
         ----------
-        available
-            True if the value box is expected to be available for full screen mode, False otherwise.
+        value
+            `True` if the element is expected to be available for full screen mode, False otherwise.
         timeout
-            The maximum time to wait for the expectation to pass. Defaults to None.
+            The maximum time to wait for the expectation to pass. Defaults to `None`.
         """
         playwright_expect(self._loc_fullscreen).to_have_count(
-            int(available), timeout=timeout
+            int(value), timeout=timeout
         )
 
 
 class ValueBox(
     _WidthLocM,
-    _CardFullScreenM,
-    _InputWithContainer,
+    _CardValueBoxFullScreenM,
+    _UiWithContainer,
 ):
     """
-    ValueBox control for :func:`~shiny.ui.value_box`
+    Value Box control for :func:`~shiny.ui.value_box`.
     """
 
     loc: Locator
     """
-    `Locator` for the value box's value
+    Playwright `Locator` for the value box's value.
     """
     loc_showcase: Locator
     """
-    `Locator` for the value box showcase
+    Playwright `Locator` for the value box showcase.
     """
     loc_title: Locator
     """
-    `Locator` for the value box title
+    Playwright `Locator` for the value box title.
     """
     loc_body: Locator
     """
-    `Locator` for the value box body
+    Playwright `Locator` for the value box body.
     """
 
     def __init__(self, page: Page, id: str) -> None:
         """
-        Initializes a new instance of the ValueBox class.
+        Initializes a new instance of the `ValueBox` class.
 
         Parameters
         ----------
         page
-            The Playwright page object.
+            Playwright `Page` of the Shiny app.
         id
             The ID of the value box.
 
@@ -2768,13 +4441,13 @@ def expect_height(self, value: StyleValue, *, timeout: Timeout = None) -> None:
         value
             The expected height value.
         timeout
-            The maximum time to wait for the expectation to pass. Defaults to None.
+            The maximum time to wait for the expectation to pass. Defaults to `None`.
         """
         expect_to_have_style(self.loc_container, "max-height", value, timeout=timeout)
 
     def expect_title(
         self,
-        text: PatternOrStr,
+        value: PatternOrStr,
         *,
         timeout: Timeout = None,
     ) -> None:
@@ -2783,20 +4456,20 @@ def expect_title(
 
         Parameters
         ----------
-        text
+        value
             The expected text pattern or string.
         timeout
-            The maximum time to wait for the expectation to pass. Defaults to None.
+            The maximum time to wait for the expectation to pass. Defaults to `None`.
 
         """
         playwright_expect(self.loc_title).to_have_text(
-            text,
+            value,
             timeout=timeout,
         )
 
     def expect_value(
         self,
-        text: PatternOrStr,
+        value: PatternOrStr,
         *,
         timeout: Timeout = None,
     ) -> None:
@@ -2805,19 +4478,19 @@ def expect_value(
 
         Parameters
         ----------
-        text
+        value
             The expected text pattern or string.
         timeout
-            The maximum time to wait for the expectation to pass. Defaults to None.
+            The maximum time to wait for the expectation to pass. Defaults to `None`.
         """
         playwright_expect(self.loc).to_have_text(
-            text,
+            value,
             timeout=timeout,
         )
 
     def expect_body(
         self,
-        text: PatternOrStr | list[PatternOrStr],
+        value: PatternOrStr | list[PatternOrStr],
         *,
         timeout: Timeout = None,
     ) -> None:
@@ -2826,48 +4499,59 @@ def expect_body(
 
         Parameters
         ----------
-        text
+        value
             The expected text pattern or list of patterns/strings.
-            Note: If testing against multiple elements, text should be an array
+
+            Note: If testing against multiple elements, text should be an array.
         timeout
-            The maximum time to wait for the expectation to pass. Defaults to None.
+            The maximum time to wait for the expectation to pass. Defaults to `None`.
         """
         playwright_expect(self.loc_body).to_have_text(
-            text,
+            value,
             timeout=timeout,
         )
 
 
-class Card(_WidthLocM, _CardFooterM, _CardBodyM, _CardFullScreenM, _InputWithContainer):
+class Card(
+    _WidthLocM,
+    _CardFooterM,
+    _CardBodyM,
+    _CardValueBoxFullScreenM,
+    _UiWithContainer,
+):
     """
-    Card control for :func:`~shiny.ui.card`
+    Card control for :func:`~shiny.ui.card`.
     """
 
+    loc_container: Locator
+    """
+    Playwright `Locator` for the card container.
+    """
     loc: Locator
     """
-    `Locator` for the card's value
+    Playwright `Locator` for the card's value.
     """
     loc_title: Locator
     """
-    `Locator` for the card title
+    Playwright `Locator` for the card title.
     """
     loc_footer: Locator
     """
-    `Locator` for the card footer
+    Playwright `Locator` for the card footer.
     """
     loc_body: Locator
     """
-    `Locator` for the card body
+    Playwright `Locator` for the card body.
     """
 
     def __init__(self, page: Page, id: str) -> None:
         """
-        Initializes a new instance of the Card class.
+        Initializes a new instance of the `Card` class.
 
         Parameters
         ----------
         page
-            The Playwright page object.
+            Playwright `Page` of the Shiny app.
         id
             The ID of the card.
         """
@@ -2893,7 +4577,7 @@ def __init__(self, page: Page, id: str) -> None:
 
     def expect_header(
         self,
-        text: PatternOrStr | None,
+        value: PatternOrStr | None,
         *,
         timeout: Timeout = None,
     ) -> None:
@@ -2902,16 +4586,17 @@ def expect_header(
 
         Parameters
         ----------
-        text
-            The expected text pattern or string
-            Note: None if the header is expected to not exist.
+        value
+            The expected text pattern or string.
+
+            Note: `None` if the header is expected to not exist.
         timeout
-            The maximum time to wait for the expectation to pass. Defaults to None.
+            The maximum time to wait for the expectation to pass. Defaults to `None`.
         """
-        if text is None:
+        if value is None:
             playwright_expect(self.loc_title).to_have_count(0, timeout=timeout)
         else:
-            playwright_expect(self.loc_title).to_have_text(text, timeout=timeout)
+            playwright_expect(self.loc_title).to_have_text(value, timeout=timeout)
 
     # def expect_body(
     #     self,
@@ -2928,7 +4613,7 @@ def expect_header(
 
     def expect_footer(
         self,
-        text: PatternOrStr | None,
+        value: PatternOrStr | None,
         *,
         timeout: Timeout = None,
     ) -> None:
@@ -2937,16 +4622,16 @@ def expect_footer(
 
         Parameters
         ----------
-        text
+        value
             The expected text pattern or string
             Note: None if the footer is expected to not exist.
         timeout
-            The maximum time to wait for the expectation to pass. Defaults to None.
+            The maximum time to wait for the expectation to pass. Defaults to `None`.
         """
-        if text is None:
+        if value is None:
             playwright_expect(self.loc_footer).to_have_count(0, timeout=timeout)
         else:
-            playwright_expect(self.loc_footer).to_have_text(text, timeout=timeout)
+            playwright_expect(self.loc_footer).to_have_text(value, timeout=timeout)
 
     def expect_max_height(self, value: StyleValue, *, timeout: Timeout = None) -> None:
         """
@@ -2957,7 +4642,7 @@ def expect_max_height(self, value: StyleValue, *, timeout: Timeout = None) -> No
         value
             The expected maximum height value.
         timeout
-            The maximum time to wait for the expectation to pass. Defaults to None.
+            The maximum time to wait for the expectation to pass. Defaults to `None`.
         """
         expect_to_have_style(self.loc_container, "max-height", value, timeout=timeout)
 
@@ -2970,7 +4655,7 @@ def expect_min_height(self, value: StyleValue, *, timeout: Timeout = None) -> No
         value
             The expected minimum height value.
         timeout
-            The maximum time to wait for the expectation to pass. Defaults to None.
+            The maximum time to wait for the expectation to pass. Defaults to `None`.
         """
         expect_to_have_style(self.loc_container, "min-height", value, timeout=timeout)
 
@@ -2983,43 +4668,80 @@ def expect_height(self, value: StyleValue, *, timeout: Timeout = None) -> None:
         value
             The expected height value.
         timeout
-            The maximum time to wait for the expectation to pass. Defaults to None.
+            The maximum time to wait for the expectation to pass. Defaults to `None`.
         """
         expect_to_have_style(self.loc_container, "height", value, timeout=timeout)
 
 
 class Accordion(
     _WidthLocM,
-    _InputWithContainer,
+    _UiWithContainer,
 ):
-    # *args: AccordionPanel | TagAttrs,
-    # id: Optional[str] = None,
-    # open: Optional[bool | str | list[str]] = None,
-    # multiple: bool = True,
-    # class_: Optional[str] = None,
-    # width: Optional[CssUnit] = None,
-    # height: Optional[CssUnit] = None,
-    # **kwargs: TagAttrValue,
+    """Accordion control for :func:`~shiny.ui.accordion`."""
+
+    loc: Locator
+    """
+    Playwright `Locator` for each accordion items.
+    """
+    loc_container: Locator
+    """
+    Playwright `Locator` for the accordion container.
+    """
+    # loc_open: Locator
+    # """
+    # `Locator` for the open accordion panel
+    # """
+
     def __init__(self, page: Page, id: str) -> None:
+        """
+        Initializes a new instance of the `Accordion` class.
+
+        Parameters
+        ----------
+        page
+            Playwright `Page` of the Shiny app.
+        id
+            The ID of the accordion.
+        """
         super().__init__(
             page,
             id=id,
             loc="> div.accordion-item",
             loc_container=f"div#{id}.accordion.shiny-bound-input",
         )
-        self.loc_open = self.loc.locator(
-            # Return self
-            "xpath=.",
-            # Simple approach as position is not needed
-            has=page.locator(
-                "> div.accordion-collapse.show",
-            ),
-        )
+        # self.loc_open = self.loc.locator(
+        #     # Return self
+        #     "xpath=.",
+        #     # Simple approach as position is not needed
+        #     has=page.locator(
+        #         "> div.accordion-collapse.show",
+        #     ),
+        # )
 
     def expect_height(self, value: StyleValue, *, timeout: Timeout = None) -> None:
+        """
+        Expects the accordion to have the specified height.
+
+        Parameters
+        ----------
+        value
+            The expected height.
+        timeout
+            The maximum time to wait for the height to be visible and interactable. Defaults to `None`.
+        """
         expect_to_have_style(self.loc_container, "height", value, timeout=timeout)
 
     def expect_width(self, value: StyleValue, *, timeout: Timeout = None) -> None:
+        """
+        Expects the accordion to have the specified width.
+
+        Parameters
+        ----------
+        value
+            The expected width.
+        timeout
+            The maximum time to wait for the width to be visible and interactable. Defaults to `None`.
+        """
         expect_to_have_style(self.loc_container, "width", value, timeout=timeout)
 
     def expect_open(
@@ -3048,6 +4770,16 @@ def expect_panels(
         *,
         timeout: Timeout = None,
     ) -> None:
+        """
+        Expects the accordion to have the specified panels.
+
+        Parameters
+        ----------
+        value
+            The expected panels.
+        timeout
+            The maximum time to wait for the panels to be visible and interactable. Defaults to `None`.
+        """
         _MultipleDomItems.expect_locator_values_in_list(
             page=self.page,
             loc_container=self.loc_container,
@@ -3064,6 +4796,16 @@ def set(
         *,
         timeout: Timeout = None,
     ) -> None:
+        """
+        Sets the state of the accordion panel.
+
+        Parameters
+        ----------
+        selected
+            The selected accordion panel(s).
+        timeout
+            The maximum time to wait for the accordion panel to be visible and interactable. Defaults to `None`.
+        """
         if isinstance(selected, str):
             selected = [selected]
         for element in self.loc.element_handles():
@@ -3082,21 +4824,59 @@ def accordion_panel(
         self,
         data_value: str,
     ) -> AccordionPanel:
+        """
+        Returns the accordion panel with the specified data value.
+
+        Parameters
+        ----------
+        data_value
+            The data value of the accordion panel.
+        """
         return AccordionPanel(self.page, self.id, data_value)
 
 
 class AccordionPanel(
     _WidthLocM,
-    _InputWithContainer,
+    _UiWithContainer,
 ):
-    #    self,
-    #     *args: TagChild | TagAttrs,
-    #     data_value: str,
-    #     icon: TagChild | None,
-    #     title: TagChild | None,
-    #     id: str | None,
-    #     **kwargs: TagAttrValue,
+    """
+    AccordionPanel control for :func:`~shiny.ui.accordion_panel`.
+    """
+
+    loc_label: Locator
+    """
+    Playwright `Locator` for the accordion panel's label.
+    """
+    loc_icon: Locator
+    """
+    Playwright `Locator` for the accordion panel's icon.
+    """
+    loc_body: Locator
+    """
+    Playwright `Locator` for the accordion panel's body.
+    """
+    loc_header: Locator
+    """
+    Playwright `Locator` for the accordion panel's header.
+    """
+    # loc_body_visible: Locator
+    # """
+    # Playwright `Locator` for the visible accordion panel body
+    # """
+
     def __init__(self, page: Page, id: str, data_value: str) -> None:
+        """
+        Initializes a new instance of the `AccordionPanel` class.
+
+        Parameters
+        ----------
+        page
+            Playwright `Page` of the Shiny app.
+        id
+            The ID of the accordion panel.
+        data_value
+            The data value of the accordion panel.
+        """
         super().__init__(
             page,
             id=id,
@@ -3114,35 +4894,108 @@ def __init__(self, page: Page, id: str, data_value: str) -> None:
 
         self.loc_body = self.loc.locator("> .accordion-collapse")
         self.loc_header = self.loc.locator("> .accordion-header")
-        self.loc_body_visible = self.loc.locator("> .accordion-collapse.show")
+        self._loc_body_visible = self.loc.locator("> .accordion-collapse.show")
 
     def expect_label(self, value: PatternOrStr, *, timeout: Timeout = None) -> None:
+        """
+        Expects the accordion panel label to have the specified text.
+
+        Parameters
+        ----------
+        value
+            The expected text pattern or string.
+        timeout
+            The maximum time to wait for the label to appear. Defaults to `None`.
+        """
         playwright_expect(self.loc_label).to_have_text(value, timeout=timeout)
 
     def expect_body(self, value: PatternOrStr, *, timeout: Timeout = None) -> None:
+        """
+        Expects the accordion panel body to have the specified text.
+
+        Parameters
+        ----------
+        value
+            The expected text pattern or string.
+        timeout
+            The maximum time to wait for the body to appear. Defaults to `None`.
+        """
         playwright_expect(self.loc_body).to_have_text(value, timeout=timeout)
 
     def expect_icon(self, value: PatternOrStr, *, timeout: Timeout = None) -> None:
+        """
+        Expects the accordion panel icon to have the specified text.
+
+        Parameters
+        ----------
+        value
+            The expected text pattern or string.
+        timeout
+            The maximum time to wait for the icon to appear. Defaults to `None`.
+        """
         playwright_expect(self.loc_icon).to_have_text(value, timeout=timeout)
 
-    def expect_open(self, is_open: bool, *, timeout: Timeout = None) -> None:
-        _expect_class_value(self.loc_body, "show", is_open, timeout=timeout)
+    def expect_open(self, value: bool, *, timeout: Timeout = None) -> None:
+        """
+        Expects the accordion panel to be open or closed.
+
+        Parameters
+        ----------
+        value
+            `True` if the accordion panel is expected to be open, `False` otherwise.
+        timeout
+            The maximum time to wait for the expectation to pass. Defaults to `None`.
+        """
+        _expect_class_value(self.loc_body, "show", value, timeout=timeout)
 
     # user sends value of Open: true | false
     def set(self, open: bool, *, timeout: Timeout = None) -> None:
+        """
+        Sets the state of the control to open or closed.
+
+        Parameters
+        ----------
+        open
+            `True` to open the accordion panel, False to close it.
+        timeout
+            The maximum time to wait for the control to be visible and interactable. Defaults to `None`.
+        """
         self.loc.wait_for(state="visible", timeout=timeout)
         self.loc.scroll_into_view_if_needed(timeout=timeout)
         expect_not_to_have_class(self.loc_body, "collapsing", timeout=timeout)
-        if self.loc_body_visible.count() != int(open):
+        if self._loc_body_visible.count() != int(open):
             self.toggle(timeout=timeout)
 
     def toggle(self, *, timeout: Timeout = None) -> None:
+        """
+        Toggles the state of the control.
+
+        Parameters
+        ----------
+        timeout
+            The maximum time to wait for the control to be visible and interactable. Defaults to `None`.
+        """
         self.loc.wait_for(state="visible", timeout=timeout)
         self.loc.scroll_into_view_if_needed(timeout=timeout)
         self.loc_header.click(timeout=timeout)
 
 
-class _OverlayBase(_InputBase):
+class _OverlayBase(_UiBase):
+    """Base class for overlay controls"""
+
+    loc_trigger: Locator
+    """
+    Playwright `Locator` for the trigger element.
+    """
+    loc_overlay_body: Locator
+    """
+    Playwright `Locator` for the overlay body.
+    """
+    loc_overlay_container: Locator
+    """
+    Playwright `Locator` for of the overlay container.
+    """
+
     def __init__(
         self,
         page: Page,
@@ -3152,6 +5005,22 @@ def __init__(
         overlay_name: str,
         overlay_selector: str,
     ) -> None:
+        """
+        Initializes a new instance of the `OverlayBase` class.
+
+        Parameters
+        ----------
+        page
+            Playwright `Page` of the Shiny app.
+        id
+            The ID of the overlay.
+        loc
+            Playwright `Locator` of the overlay.
+        overlay_name
+            The name of the overlay.
+        overlay_selector
+            The selector of the overlay.
+        """
         super().__init__(page, id=id, loc=loc)
         self._overlay_name = overlay_name
         self._overlay_selector = overlay_selector
@@ -3186,23 +5055,61 @@ def get_loc_overlay_body(self, *, timeout: Timeout = None) -> Locator:
         )
 
     def get_loc_overlay_container(self, *, timeout: Timeout = None) -> Locator:
+        """
+        Returns the locator for the overlay container.
+
+        Parameters
+        ----------
+        timeout
+            The maximum time to wait for the overlay container to appear. Defaults to `None`.
+        """
         return self.page.locator(f"#{self._get_overlay_id(timeout=timeout)}")
 
     def expect_body(self, value: PatternOrStr, *, timeout: Timeout = None) -> None:
+        """
+        Expects the overlay body to have the specified text.
+
+        Parameters
+        ----------
+        value
+            The expected text pattern or string.
+        timeout
+            The maximum time to wait for the overlay body to appear. Defaults to `None`.
+        """
         playwright_expect(self.get_loc_overlay_body(timeout=timeout)).to_have_text(
             value, timeout=timeout
         )
 
-    def expect_active(self, active: bool, *, timeout: Timeout = None) -> None:
-        value = re.compile(r".*") if active else None
+    def expect_active(self, value: bool, *, timeout: Timeout = None) -> None:
+        """
+        Expects the overlay to be active or inactive.
+
+        Parameters
+        ----------
+        value
+            `True` if the overlay is expected to be active, False otherwise.
+        timeout
+            The maximum time to wait for the expectation to pass. Defaults to `None`.
+        """
+        attr_value = re.compile(r".*") if value else None
         return expect_attribute_to_have_value(
             loc=self.loc_trigger,
             timeout=timeout,
             name="aria-describedby",
-            value=value,
+            value=attr_value,
         )
 
     def expect_placement(self, value: str, *, timeout: Timeout = None) -> None:
+        """
+        Expects the overlay to have the specified placement.
+
+        Parameters
+        ----------
+        value
+            The expected placement value.
+        timeout
+            The maximum time to wait for the expectation to pass. Defaults to `None`.
+        """
         return expect_attribute_to_have_value(
             loc=self.get_loc_overlay_container(timeout=timeout),
             timeout=timeout,
@@ -3212,14 +5119,32 @@ def expect_placement(self, value: str, *, timeout: Timeout = None) -> None:
 
 
 class Popover(_OverlayBase):
-    # trigger: TagChild,
-    # *args: TagChild | TagAttrs,
-    # title: Optional[TagChild] = None,
-    # id: Optional[str] = None,
-    # placement: Literal["auto", "top", "right", "bottom", "left"] = "auto",
-    # options: Optional[dict[str, Any]] = None,
-    # **kwargs: TagAttrValue,
+    """Popover control for :func:`~shiny.ui.popover`."""
+
+    loc_trigger: Locator
+    """
+    Playwright `Locator` for the trigger element that opens/closes the popover.
+    """
+    loc_overlay_body: Locator
+    """
+    Playwright `Locator` for the popover body.
+    """
+    loc_overlay_container: Locator
+    """
+    Playwright `Locator` for the popover container.
+    """
+
     def __init__(self, page: Page, id: str) -> None:
+        """
+        Initializes a new instance of the `Popover` class.
+
+        Parameters
+        ----------
+        page
+            Playwright `Page` of the Shiny app.
+        id
+            The ID of the popover.
+        """
         super().__init__(
             page,
             id=id,
@@ -3229,23 +5154,68 @@ def __init__(self, page: Page, id: str) -> None:
         )
 
     def set(self, open: bool, timeout: Timeout = None) -> None:
+        """
+        Sets the state of the popover.
+
+        Parameters
+        ----------
+        open
+            `True` to open the popover and `False` to close it.
+        timeout
+            The maximum time to wait for the popover to be visible and interactable. Defaults to `None`.
+        """
         if open ^ self.get_loc_overlay_body(timeout=timeout).count() > 0:
             self.toggle()
 
     def toggle(self, timeout: Timeout = None) -> None:
+        """
+        Toggles the state of the popover.
+
+        Parameters
+        ----------
+        timeout
+            The maximum time to wait for the popover to be visible and interactable. Defaults to `None`.
+        """
         self.loc_trigger.wait_for(state="visible", timeout=timeout)
         self.loc_trigger.scroll_into_view_if_needed(timeout=timeout)
         self.loc_trigger.click(timeout=timeout)
 
 
-class Tooltip(_OverlayBase):
-    # trigger: TagChild,
-    # *args: TagChild | TagAttrs,
-    # id: Optional[str] = None,
-    # placement: Literal["auto", "top", "right", "bottom", "left"] = "auto",
-    # options: Optional[dict[str, object]] = None,
-    # **kwargs: TagAttrValue,
+class Tooltip(_OverlayBase):
+    """Tooltip control for :func:`~shiny.ui.tooltip`."""
+
+    loc_container: Locator
+    """
+    Playwright `Locator` for the container tooltip.
+    """
+    loc: Locator
+    """
+    Playwright `Locator` for the tooltip content.
+    """
+    loc_trigger: Locator
+    """
+    Playwright `Locator` for the trigger element.
+    """
+    loc_overlay_body: Locator
+    """
+    Playwright `Locator` for the overlay body.
+    """
+    loc_overlay_container: Locator
+    """
+    Playwright `Locator` for the overlay container.
+    """
+
     def __init__(self, page: Page, id: str) -> None:
+        """
+        Initializes a new instance of the `Tooltip` class.
+
+        Parameters
+        ----------
+        page
+            Playwright `Page` of the Shiny app.
+        id
+            The ID of the tooltip.
+        """
         super().__init__(
             page,
             id=id,
@@ -3255,18 +5225,38 @@ def __init__(self, page: Page, id: str) -> None:
         )
 
     def set(self, open: bool, timeout: Timeout = None) -> None:
+        """
+        Sets the state of the tooltip.
+
+        Parameters
+        ----------
+        open
+            `True` to open the tooltip and `False` to close it.
+        timeout
+            The maximum time to wait for the tooltip to be visible and interactable. Defaults to `None`.
+        """
         if open ^ self.get_loc_overlay_body(timeout=timeout).count() > 0:
             self.toggle(timeout=timeout)
         if not open:
             self.get_loc_overlay_body(timeout=timeout).click()
 
     def toggle(self, timeout: Timeout = None) -> None:
+        """
+        Toggles the state of the tooltip.
+
+        Parameters
+        ----------
+        timeout
+            The maximum time to wait for the tooltip to be visible and interactable. Defaults to `None`.
+        """
         self.loc_trigger.wait_for(state="visible", timeout=timeout)
         self.loc_trigger.scroll_into_view_if_needed(timeout=timeout)
         self.loc_trigger.hover(timeout=timeout)
 
 
-class _NavItemBase(_InputWithContainer):
+class _NavItemBase(_UiWithContainer):
+    """A Base mixin class for Nav and NavItem controls"""
+
     def nav_item(
         self,
         value: str,
@@ -3274,9 +5264,27 @@ def nav_item(
         return NavItem(self.page, self.id, value)
 
     def set(self, value: str, *, timeout: Timeout = None) -> None:
+        """
+        Sets the state of the control to open or closed.
+
+        Parameters
+        ----------
+        value
+            The selected nav item.
+        """
         self.nav_item(value).click(timeout=timeout)
 
     def expect_value(self, value: PatternOrStr, *, timeout: Timeout = None) -> None:
+        """
+        Expects the control to have the specified value.
+
+        Parameters
+        ----------
+        value
+            The expected value.
+        timeout
+            The maximum time to wait for the expectation to pass. Defaults to `None`.
+        """
         # data attribute of active tab and compare with value
         playwright_expect(
             self.loc_container.locator('a[role="tab"].active')
@@ -3292,12 +5300,30 @@ def expect_value(self, value: PatternOrStr, *, timeout: Timeout = None) -> None:
     #     )
 
     def get_loc_active_content(self, *, timeout: Timeout = None) -> Locator:
+        """
+        Returns the locator for the active content.
+
+        Parameters
+        ----------
+        timeout
+            The maximum time to wait for the locator to appear. Defaults to `None`.
+        """
         datatab_id = self.loc_container.get_attribute("data-tabsetid", timeout=timeout)
         return self.page.locator(
             f"div.tab-content[data-tabsetid='{datatab_id}'] > div.tab-pane.active"
         )
 
     def expect_content(self, value: PatternOrStr, *, timeout: Timeout = None) -> None:
+        """
+        Expects the control to have the specified content.
+
+        Parameters
+        ----------
+        value
+            The expected content.
+        timeout
+            The maximum time to wait for the expectation to pass. Defaults to `None`.
+        """
         playwright_expect(self.get_loc_active_content()).to_have_text(
             value, timeout=timeout
         )
@@ -3308,6 +5334,16 @@ def expect_nav_values(
         *,
         timeout: Timeout = None,
     ) -> None:
+        """
+        Expects the control to have the specified nav values.
+
+        Parameters
+        ----------
+        value
+            The expected nav values.
+        timeout
+            The maximum time to wait for the expectation to pass. Defaults to `None`.
+        """
         _MultipleDomItems.expect_locator_values_in_list(
             page=self.page,
             loc_container=self.loc_container,
@@ -3324,16 +5360,47 @@ def expect_nav_titles(
         *,
         timeout: Timeout = None,
     ) -> None:
+        """
+        Expects the control to have the specified nav titles.
+
+        Parameters
+        ----------
+        value
+            The expected nav titles.
+        timeout
+            The maximum time to wait for the expectation to pass. Defaults to `None`.
+        """
         self.expect.to_have_text(value, timeout=timeout)
 
 
-class NavItem(_InputWithContainer):
-    # *args: NavsetArg,
-    # id: Optional[str] = None,
-    # selected: Optional[str] = None,
-    # header: TagChild = None,
-    # footer: TagChild = None,
+class NavItem(_UiWithContainer):
+    """Navigation item control for :func:`~shiny.ui.nav_item`."""
+
+    """
+    Playwright `Locator` for the content of the nav item.
+    """
+    loc: Locator
+    """
+    Playwright `Locator` for the nav item.
+    """
+    loc_container: Locator
+    """
+    Playwright `Locator` for the nav item container.
+    """
+
     def __init__(self, page: Page, id: str, data_value: str) -> None:
+        """
+        Initializes a new instance of the `NavItem` class.
+
+        Parameters
+        ----------
+        page
+            Playwright `Page` of the Shiny app.
+        id
+            The ID of the nav item.
+        data_value
+            The data value of the nav item.
+        """
         super().__init__(
             page,
             id=id,
@@ -3347,29 +5414,77 @@ def __init__(self, page: Page, id: str, data_value: str) -> None:
     # get active content instead of assertion
     @property
     def loc_content(self) -> Locator:
-        """Note. This requires 2 steps. Will not work if the overlay element is rapidly created during locator fetch"""
+        """
+        Returns the locator for the content of the nav item.
+
+        Note: This requires 2 steps. Will not work if the overlay element is rapidly created during locator fetch
+        """
         datatab_id = self.loc_container.get_attribute("data-tabsetid")
         return self.page.locator(
             f"div.tab-content[data-tabsetid='{datatab_id}'] > div.tab-pane[data-value='{self._data_value}']"
         )
 
     def click(self, *, timeout: Timeout = None) -> None:
+        """
+        Clicks the nav item.
+
+        Parameters
+        ----------
+        timeout
+            The maximum time to wait for the nav item to be visible and interactable. Defaults to `None`.
+        """
         self.loc.click(timeout=timeout)
 
-    def expect_active(self, active: bool, *, timeout: Timeout = None) -> None:
-        _expect_class_value(self.loc, "active", active, timeout=timeout)
+    def expect_active(self, value: bool, *, timeout: Timeout = None) -> None:
+        """
+        Expects the nav item to be active or inactive.
+
+        Parameters
+        ----------
+        active
+            `True` if the nav item is expected to be active, False otherwise.
+        timeout
+            The maximum time to wait for the expectation to pass. Defaults to `None`.
+        """
+        _expect_class_value(self.loc, "active", value, timeout=timeout)
 
     def expect_content(self, value: PatternOrStr, *, timeout: Timeout = None) -> None:
+        """
+        Expects the nav item content to have the specified text.
+
+        Parameters
+        ----------
+        value
+            The expected text pattern or string.
+        timeout
+            The maximum time to wait for the expectation to pass. Defaults to `None`.
+        """
         playwright_expect(self.loc_content).to_have_text(value, timeout=timeout)
 
 
 class NavsetTab(_NavItemBase):
-    # *args: NavsetArg,
-    # id: Optional[str] = None,
-    # selected: Optional[str] = None,
-    # header: TagChild = None,
-    # footer: TagChild = None,
+    """NavsetTab control for :func:`~shiny.ui.navset_tab`."""
+
+    loc: Locator
+    """
+    Playwright `Locator` for the nav set tab.
+    """
+    loc_container: Locator
+    """
+    Playwright `Locator` for the nav set tab container.
+    """
+
     def __init__(self, page: Page, id: str) -> None:
+        """
+        Initializes a new instance of the `NavsetTab` class.
+
+        Parameters
+        ----------
+        page
+            Playwright `Page` of the Shiny app.
+        id
+            The ID of the nav set tab.
+        """
         super().__init__(
             page,
             id=id,
@@ -3379,7 +5494,19 @@ def __init__(self, page: Page, id: str) -> None:
 
 
 class NavsetPill(_NavItemBase):
+    """NavsetPill control for :func:`~shiny.ui.navset_pill`."""
+
     def __init__(self, page: Page, id: str) -> None:
+        """
+        Initializes a new instance of the `NavsetPill` class.
+
+        Parameters
+        ----------
+        page
+            Playwright `Page` of the Shiny app.
+        id
+            The ID of the nav set pill.
+        """
         super().__init__(
             page,
             id=id,
@@ -3389,7 +5516,19 @@ def __init__(self, page: Page, id: str) -> None:
 
 
 class NavsetUnderline(_NavItemBase):
+    """NavsetUnderline control for :func:`~shiny.ui.navset_underline`."""
+
     def __init__(self, page: Page, id: str) -> None:
+        """
+        Initializes a new instance of the `NavsetUnderline` class.
+
+        Parameters
+        ----------
+        page
+            Playwright `Page` of the Shiny app.
+        id
+            The ID of the nav set underline.
+        """
         super().__init__(
             page,
             id=id,
@@ -3399,7 +5538,19 @@ def __init__(self, page: Page, id: str) -> None:
 
 
 class NavsetPillList(_NavItemBase):
+    """NavsetPillList control for :func:`~shiny.ui.navset_pill_list`."""
+
     def __init__(self, page: Page, id: str) -> None:
+        """
+        Initializes a new instance of the `NavsetPillList` class.
+
+        Parameters
+        ----------
+        page
+            Playwright `Page` of the Shiny app.
+        id
+            The ID of the nav set pill list.
+        """
         super().__init__(
             page,
             id=id,
@@ -3409,7 +5560,19 @@ def __init__(self, page: Page, id: str) -> None:
 
 
 class NavsetCardTab(_NavItemBase):
+    """NavsetCardTab control for :func:`~shiny.ui.navset_card_tab`."""
+
     def __init__(self, page: Page, id: str) -> None:
+        """
+        Initializes a new instance of the `NavsetCardTab` class.
+
+        Parameters
+        ----------
+        page
+            Playwright `Page` of the Shiny app.
+        id
+            The ID of the nav set card tab.
+        """
         super().__init__(
             page,
             id=id,
@@ -3419,7 +5582,19 @@ def __init__(self, page: Page, id: str) -> None:
 
 
 class NavsetCardPill(_NavItemBase):
+    """NavsetCardPill control for :func:`~shiny.ui.navset_card_pill`."""
+
     def __init__(self, page: Page, id: str) -> None:
+        """
+        Initializes a new instance of the `NavsetCardPill` class.
+
+        Parameters
+        ----------
+        page
+            Playwright `Page` of the Shiny app.
+        id
+            The ID of the nav set card pill.
+        """
         super().__init__(
             page,
             id=id,
@@ -3429,7 +5604,19 @@ def __init__(self, page: Page, id: str) -> None:
 
 
 class NavsetCardUnderline(_NavItemBase):
+    """NavsetCardUnderline control for :func:`~shiny.ui.navset_card_underline`."""
+
     def __init__(self, page: Page, id: str) -> None:
+        """
+        Initializes a new instance of the `NavsetCardUnderline` class.
+
+        Parameters
+        ----------
+        page
+            Playwright `Page` of the Shiny app.
+        id
+            The ID of the nav set card underline.
+        """
         super().__init__(
             page,
             id=id,
@@ -3439,7 +5626,19 @@ def __init__(self, page: Page, id: str) -> None:
 
 
 class NavsetHidden(_NavItemBase):
+    """NavsetHidden control for :func:`~shiny.ui.navset_hidden`."""
+
     def __init__(self, page: Page, id: str) -> None:
+        """
+        Initializes a new instance of the `NavsetHidden` class.
+
+        Parameters
+        ----------
+        page
+            Playwright `Page` of the Shiny app.
+        id
+            The ID of the nav set hidden.
+        """
         super().__init__(
             page,
             id=id,
@@ -3449,7 +5648,19 @@ def __init__(self, page: Page, id: str) -> None:
 
 
 class NavsetBar(_NavItemBase):
+    """NavsetBar control for :func:`~shiny.ui.navset_bar`."""
+
     def __init__(self, page: Page, id: str) -> None:
+        """
+        Initializes a new instance of the `NavsetBar` class.
+
+        Parameters
+        ----------
+        page
+            Playwright `Page` of the Shiny app.
+        id
+            The ID of the nav set bar.
+        """
         super().__init__(
             page,
             id=id,
@@ -3458,32 +5669,36 @@ def __init__(self, page: Page, id: str) -> None:
         )
 
 
-class OutputDataFrame(_InputWithContainer):
+class OutputDataFrame(_UiWithContainer):
     """
-    OutputDataFrame control for :func:`~shiny.ui.output_data_frame`
+    OutputDataFrame control for :func:`~shiny.ui.output_data_frame`.
     """
 
+    loc_container: Locator
+    """
+    Playwright `Locator` for the data frame container.
+    """
     loc: Locator
     """
-    `Locator` for the data frame
+    Playwright `Locator` for the data frame.
     """
     loc_head: Locator
     """
-    `Locator` for the data frame columns
+    Playwright `Locator` for the head of the data frame table.
     """
     loc_body: Locator
     """
-    `Locator` for the data frame rows
+    Playwright `Locator` for the body of the data frame table.
     """
 
     def __init__(self, page: Page, id: str) -> None:
         """
-        Initializes a new instance of the OutputDataFrame class.
+        Initializes a new instance of the `OutputDataFrame` class.
 
         Parameters
         ----------
         page
-            The Playwright page object.
+            Playwright `Page` of the Shiny app.
         id
             The ID of the data frame.
         """
@@ -3514,24 +5729,24 @@ def cell_locator(self, row: int, col: int) -> Locator:
             f"> td:nth-child({col + 1}),  > th:nth-child({col + 1})"
         )
 
-    def expect_n_row(self, row_number: int, *, timeout: Timeout = None):
+    def expect_n_row(self, value: int, *, timeout: Timeout = None):
         """
         Expects the number of rows in the data frame.
 
         Parameters
         ----------
-        row_number
+        value
             The expected number of rows.
         timeout
-            The maximum time to wait for the expectation to pass. Defaults to None.
+            The maximum time to wait for the expectation to pass. Defaults to `None`.
         """
         playwright_expect(self.loc_body.locator("> tr")).to_have_count(
-            row_number, timeout=timeout
+            value, timeout=timeout
         )
 
     def expect_cell(
         self,
-        text: PatternOrStr,
+        value: PatternOrStr,
         *,
         row: int,
         col: int,
@@ -3542,25 +5757,25 @@ def expect_cell(
 
         Parameters
         ----------
-        text
+        value
             The expected text in the cell.
         row
             The row number of the cell.
         col
             The column number of the cell.
         timeout
-            The maximum time to wait for the expectation to pass. Defaults to None.
+            The maximum time to wait for the expectation to pass. Defaults to `None`.
         """
         assert_type(row, int)
         assert_type(col, int)
         self._cell_scroll_if_needed(row=row, col=col, timeout=timeout)
         playwright_expect(self.cell_locator(row, col)).to_have_text(
-            text, timeout=timeout
+            value, timeout=timeout
         )
 
     def expect_column_labels(
         self,
-        labels: ListPatternOrStr | None,
+        value: ListPatternOrStr | None,
         *,
         timeout: Timeout = None,
     ) -> None:
@@ -3569,22 +5784,23 @@ def expect_column_labels(
 
         Parameters
         ----------
-        labels
+        value
             The expected column labels.
+
             Note: None if the column labels are expected to not exist.
         edit
-            True if the data frame is in edit mode, False otherwise.
+            `True` if the data frame is to be in edit mode, `False` otherwise.
         timeout
-            The maximum time to wait for the expectation to pass. Defaults to None.
+            The maximum time to wait for the expectation to pass. Defaults to `None`.
         """
-        if isinstance(labels, list) and len(labels) == 0:
-            labels = None
+        if isinstance(value, list) and len(value) == 0:
+            value = None
 
-        if labels is None:
+        if value is None:
             playwright_expect(self.loc_column_label).to_have_count(0, timeout=timeout)
         else:
             playwright_expect(self.loc_column_label).to_have_text(
-                labels, timeout=timeout
+                value, timeout=timeout
             )
 
     def _cell_scroll_if_needed(self, *, row: int, col: int, timeout: Timeout):
@@ -3630,7 +5846,7 @@ def _cell_scroll_if_needed(self, *, row: int, col: int, timeout: Timeout):
 
     def expect_column_label(
         self,
-        text: ListPatternOrStr,
+        value: ListPatternOrStr,
         *,
         col: int,
         timeout: Timeout = None,
@@ -3640,23 +5856,23 @@ def expect_column_label(
 
         Parameters
         ----------
+        value
+            The expected text in the column.
         col
             The column number.
-        text
-            The expected text in the column.
         timeout
-            The maximum time to wait for the expectation to pass. Defaults to None.
+            The maximum time to wait for the expectation to pass. Defaults to `None`.
         """
         assert_type(col, int)
         # It's zero based, nth(0) selects the first element.
         playwright_expect(self.loc_column_label.nth(col - 1)).to_have_text(
-            text,
+            value,
             timeout=timeout,
         )
 
     def expect_n_col(
         self,
-        n: int,
+        value: int,
         *,
         timeout: Timeout = None,
     ) -> None:
@@ -3665,19 +5881,19 @@ def expect_n_col(
 
         Parameters
         ----------
-        n
+        value
             The expected number of columns.
         timeout
-            The maximum time to wait for the expectation to pass. Defaults to None.
+            The maximum time to wait for the expectation to pass. Defaults to `None`.
         """
         playwright_expect(self.loc_column_label).to_have_count(
-            n,
+            value,
             timeout=timeout,
         )
 
     def expect_cell_class(
         self,
-        class_: str,
+        value: str,
         *,
         row: int,
         col: int,
@@ -3688,24 +5904,24 @@ def expect_cell_class(
 
         Parameters
         ----------
+        value
+            The expected class of the cell.
         row
             The row number of the cell.
         col
             The column number of the cell.
-        class_
-            The expected class of the cell.
         timeout
-            The maximum time to wait for the expectation to pass. Defaults to None.
+            The maximum time to wait for the expectation to pass. Defaults to `None`.
         """
         expect_to_have_class(
             self.cell_locator(row=row, col=col),
-            class_,
+            value,
             timeout=timeout,
         )
 
     def select_rows(
         self,
-        rows: list[int],
+        value: list[int],
         *,
         timeout: Timeout = None,
     ) -> None:
@@ -3714,18 +5930,18 @@ def select_rows(
 
         Parameters
         ----------
-        rows
+        value
             The list of row numbers to select.
         timeout
-            The maximum time to wait for the action to complete. Defaults to None.
+            The maximum time to wait for the action to complete. Defaults to `None`.
         """
-        if len(rows) > 1:
-            rows = sorted(rows)
+        if len(value) > 1:
+            value = sorted(value)
             # check if the items in the row contain all numbers from index 0 to index -1
-            if rows == list(range(rows[0], rows[-1] + 1)):
+            if value == list(range(value[0], value[-1] + 1)):
                 self.page.keyboard.down("Shift")
-                self.cell_locator(row=rows[0], col=0).click(timeout=timeout)
-                self.cell_locator(row=rows[-1], col=0).click(timeout=timeout)
+                self.cell_locator(row=value[0], col=0).click(timeout=timeout)
+                self.cell_locator(row=value[-1], col=0).click(timeout=timeout)
                 self.page.keyboard.up("Shift")
             else:
                 # if operating system is MacOs use Meta (Cmd) else use Ctrl key
@@ -3733,7 +5949,7 @@ def select_rows(
                     self.page.keyboard.down("Meta")
                 else:
                     self.page.keyboard.down("Control")
-                for row in rows:
+                for row in value:
                     self._cell_scroll_if_needed(row=row, col=0, timeout=timeout)
                     self.cell_locator(row=row, col=0).click(timeout=timeout)
                 if platform.system() == "Darwin":
@@ -3741,11 +5957,11 @@ def select_rows(
                 else:
                     self.page.keyboard.up("Control")
         else:
-            self.cell_locator(row=rows[0], col=0).click(timeout=timeout)
+            self.cell_locator(row=value[0], col=0).click(timeout=timeout)
 
     def expect_class_state(
         self,
-        state: str,
+        value: str,
         *,
         row: int,
         col: int,
@@ -3753,18 +5969,29 @@ def expect_class_state(
     ):
         """
         Expects the state of the class in the data frame.
+
+        Parameters
+        ----------
+        value
+            The expected state of the class.
+        row
+            The row number of the cell.
+        col
+            The column number of the cell.
+        timeout
+            The maximum time to wait for the expectation to pass. Defaults to `None`.
         """
-        if state == "ready":
+        if value == "ready":
             playwright_expect(self.cell_locator(row=row, col=col)).not_to_have_class(
                 "cell-edit-editing", timeout=timeout
             )
-        elif state == "editing":
+        elif value == "editing":
             self.expect_cell_class("cell-edit-editing", row=row, col=col)
-        elif state == "saving":
+        elif value == "saving":
             self.expect_cell_class("cell-edit-saving", row=row, col=col)
-        elif state == "failure":
+        elif value == "failure":
             self.expect_cell_class("cell-edit-failure", row=row, col=col)
-        elif state == "success":
+        elif value == "success":
             self.expect_cell_class("cell-edit-success", row=row, col=col)
         else:
             raise ValueError(
@@ -3791,7 +6018,7 @@ def edit_cell(
         col
             The column number of the cell.
         timeout
-            The maximum time to wait for the action to complete. Defaults to None.
+            The maximum time to wait for the action to complete. Defaults to `None`.
         """
         cell = self.cell_locator(row=row, col=col)
 
@@ -3799,9 +6026,10 @@ def edit_cell(
         cell.click(timeout=timeout)
         cell.locator("> textarea").fill(text)
 
-    # TODO-karan-test: Rename to `set_column_sorting?`
+    # TODO-karan-test: Rename to `set_sort?`
     # TODO-karan-test: Add support for a list of columns
     # TODO-karan-test: Add support for direction
+    # TODO-karan-test: Add method for testing direction
     def set_column_sort(
         self,
         col: int,
@@ -3816,13 +6044,14 @@ def set_column_sort(
         col
             The column number to sort.
         timeout
-            The maximum time to wait for the action to complete. Defaults to None.
+            The maximum time to wait for the action to complete. Defaults to `None`.
         """
         self.loc_column_label.nth(col).click(timeout=timeout)
 
-    # TODO-karan-test: Rename to `set_column_filters?`
+    # TODO-karan-test: Rename to `set_filter?`
     # TODO-karan-test: Add support for a list of columns ? If so, all other columns should be reset
     # TODO-karan-test: Add support for a None value reset all filters
+    # TODO-karan-test: Add method for testing direction
     def set_column_filter(
         self,
         col: int,
@@ -3840,7 +6069,7 @@ def set_column_filter(
         text
             The text to filter the column.
         timeout
-            The maximum time to wait for the action to complete. Defaults to None.
+            The maximum time to wait for the action to complete. Defaults to `None`.
         """
         if isinstance(text, str):
             self.loc_column_filter.nth(col).locator("> input").fill(
@@ -3880,14 +6109,14 @@ def save_cell(
         col
             The column number of the cell.
         timeout
-            The maximum time to wait for the action to complete. Defaults to None.
+            The maximum time to wait for the action to complete. Defaults to `None`.
         """
         self.edit_cell(text, row=row, col=col, timeout=timeout)
         self.cell_locator(row=row, col=col).locator("> textarea").press(save_key)
 
     def expect_cell_title(
         self,
-        message: str,
+        value: str,
         *,
         row: int,
         col: int,
@@ -3898,24 +6127,37 @@ def expect_cell_title(
 
         Parameters
         ----------
+        value
+            The expected validation message of the cell.
         row
             The row number of the cell.
         col
             The column number of the cell.
-        message
-            The expected validation message of the cell.
         timeout
-            The maximum time to wait for the expectation to pass. Defaults to None.
+            The maximum time to wait for the expectation to pass. Defaults to `None`.
         """
-
         playwright_expect(self.cell_locator(row=row, col=col)).to_have_attribute(
-            name="title", value=message, timeout=timeout
+            name="title", value=value, timeout=timeout
         )
 
 
 # TODO: Use mixin for dowloadlink and download button
 class DownloadLink(_InputActionBase):
+    """
+    DownloadLink control for :func:`~shiny.ui.download_link`.
+    """
+
     def __init__(self, page: Page, id: str) -> None:
+        """
+        Initializes a new instance of the `DownloadLink` class.
+
+        Parameters
+        ----------
+        page
+            Playwright `Page` of the Shiny app.
+        id
+            The ID of the download link.
+        """
         super().__init__(
             page,
             id=id,
@@ -3927,7 +6169,21 @@ class DownloadButton(
     _WidthLocM,
     _InputActionBase,
 ):
+    """
+    DownloadButton control for :func:`~shiny.ui.download_button`
+    """
+
     def __init__(self, page: Page, id: str) -> None:
+        """
+        Initializes a new instance of the `DownloadButton` class.
+
+        Parameters
+        ----------
+        page
+            Playwright `Page` of the Shiny app.
+        id
+            The ID of the download button.
+        """
         super().__init__(
             page,
             id=id,


Test patch:
diff --git a/tests/playwright/shiny/components/card-input/test_card-input.py b/tests/playwright/shiny/components/card-input/test_card-input.py
index 4130b6003..7b14da909 100644
--- a/tests/playwright/shiny/components/card-input/test_card-input.py
+++ b/tests/playwright/shiny/components/card-input/test_card-input.py
@@ -27,25 +27,25 @@ def test_card_input(page: Page, app_path: str, sel_card: str, sel_vb: str) -> No
     out_vb = OutputCode(page, "out_value_box")
 
     # Open and close card full screen, check input value ------
-    card.expect_full_screen_open(False)
+    card.expect_full_screen(False)
     out_card.expect_value("False")
 
     card.open_full_screen()
-    card.expect_full_screen_open(True)
+    card.expect_full_screen(True)
     out_card.expect_value("True")
 
     card.close_full_screen()
-    card.expect_full_screen_open(False)
+    card.expect_full_screen(False)
     out_card.expect_value("False")
 
     # Open and close value box full screen, check input value ------
-    vb.expect_full_screen_open(False)
+    vb.expect_full_screen(False)
     out_vb.expect_value("False")
 
     vb.open_full_screen()
-    vb.expect_full_screen_open(True)
+    vb.expect_full_screen(True)
     out_vb.expect_value("True")
 
     vb.close_full_screen()
-    vb.expect_full_screen_open(False)
+    vb.expect_full_screen(False)
     out_vb.expect_value("False")
diff --git a/tests/playwright/shiny/components/value_box/kitchensink/test_valuebox_ks.py b/tests/playwright/shiny/components/value_box/kitchensink/test_valuebox_ks.py
index f5d72e24b..16fb9b07a 100644
--- a/tests/playwright/shiny/components/value_box/kitchensink/test_valuebox_ks.py
+++ b/tests/playwright/shiny/components/value_box/kitchensink/test_valuebox_ks.py
@@ -60,12 +60,12 @@ def test_valuebox(page: Page, local_app: ShinyAppProc) -> None:
     assert get_value_box_bg_color(value_box1) == "rgb(193, 0, 0)"
     assert get_value_box_fg_color(value_box1) == "rgb(255, 255, 255)"
     value_box1.expect_full_screen_available(True)
-    value_box1.expect_full_screen_open(False)
+    value_box1.expect_full_screen(False)
     value_box1.open_full_screen()
-    value_box1.expect_full_screen_open(True)
+    value_box1.expect_full_screen(True)
     value_box1.expect_body(["Inside the fullscreen"])
     value_box1.close_full_screen()
-    value_box1.expect_full_screen_open(False)
+    value_box1.expect_full_screen(False)
 
     value_box2 = ValueBox(page, "valuebox2")
     value_box2.expect_height(None)
diff --git a/tests/playwright/shiny/components/value_box/smoke/test_valuebox.py b/tests/playwright/shiny/components/value_box/smoke/test_valuebox.py
index badae5341..c2715289a 100644
--- a/tests/playwright/shiny/components/value_box/smoke/test_valuebox.py
+++ b/tests/playwright/shiny/components/value_box/smoke/test_valuebox.py
@@ -10,9 +10,9 @@ def test_valuebox(page: Page, local_app: ShinyAppProc, value_box_id: str) -> Non
     page.goto(local_app.url)
 
     value_box = ValueBox(page, value_box_id)
-    value_box.expect_full_screen_open(False)
+    value_box.expect_full_screen(False)
     value_box.open_full_screen()
-    value_box.expect_full_screen_open(True)
+    value_box.expect_full_screen(True)
     if value_box_id == "valuebox1":
         value_box.expect_height(None)
         value_box.expect_title("KPI Title")
@@ -30,4 +30,4 @@ def test_valuebox(page: Page, local_app: ShinyAppProc, value_box_id: str) -> Non
         )
         assert title_tag_name == "p"
     value_box.close_full_screen()
-    value_box.expect_full_screen_open(False)
+    value_box.expect_full_screen(False)
diff --git a/tests/playwright/shiny/experimental/card/kitchensink/test_card_ks.py b/tests/playwright/shiny/experimental/card/kitchensink/test_card_ks.py
index a16476c5e..276c9df10 100644
--- a/tests/playwright/shiny/experimental/card/kitchensink/test_card_ks.py
+++ b/tests/playwright/shiny/experimental/card/kitchensink/test_card_ks.py
@@ -34,11 +34,11 @@ def test_card_kitchensink(page: Page, local_app: ShinyAppProc) -> None:
             "\nThis is the body of a card with default height w/ fullscreen",
         ]
     )
-    card.expect_full_screen_open(False)
+    card.expect_full_screen(False)
     card.open_full_screen()
-    card.expect_full_screen_open(True)
+    card.expect_full_screen(True)
     card.close_full_screen()
-    card.expect_full_screen_open(False)
+    card.expect_full_screen(False)
 
     card = Card(page, "card2")
     card.expect_max_height(None)
@@ -50,7 +50,7 @@ def test_card_kitchensink(page: Page, local_app: ShinyAppProc) -> None:
         ["\nThis is the body without a header of a footer - No Fullscreen\n"]
     )
     assert get_body_tag_name(card) == "p"
-    card.expect_full_screen_open(False)
+    card.expect_full_screen(False)
     card.expect_full_screen_available(False)
 
     card = Card(page, "card3")
diff --git a/tests/playwright/shiny/experimental/card/test_card.py b/tests/playwright/shiny/experimental/card/test_card.py
index 7f06948fc..cc18b137e 100644
--- a/tests/playwright/shiny/experimental/card/test_card.py
+++ b/tests/playwright/shiny/experimental/card/test_card.py
@@ -20,8 +20,8 @@ def test_card(page: Page, local_app: ShinyAppProc) -> None:
             "\nThis is still the body.\n",
         ]
     )
-    card.expect_full_screen_open(False)
+    card.expect_full_screen(False)
     card.open_full_screen()
-    card.expect_full_screen_open(True)
+    card.expect_full_screen(True)
     card.close_full_screen()
-    card.expect_full_screen_open(False)
+    card.expect_full_screen(False)
diff --git a/tests/playwright/shiny/outputs/test_output_image.py b/tests/playwright/shiny/outputs/test_output_image.py
index 071352a8e..f1c3c0e06 100644
--- a/tests/playwright/shiny/outputs/test_output_image.py
+++ b/tests/playwright/shiny/outputs/test_output_image.py
@@ -14,7 +14,7 @@ def test_output_image_kitchen(page: Page, app: ShinyAppProc) -> None:
 
     img = OutputImage(page, "image")
 
-    img.expect_inline(inline=False)
+    img.expect_inline(False)
 
     img.expect_img_src(re.compile(r"data:image/png;base64"))
     img.expect_img_height(None)
diff --git a/tests/playwright/shiny/outputs/test_output_plot.py b/tests/playwright/shiny/outputs/test_output_plot.py
index 67ae9664a..e2cfb59f3 100644
--- a/tests/playwright/shiny/outputs/test_output_plot.py
+++ b/tests/playwright/shiny/outputs/test_output_plot.py
@@ -14,7 +14,7 @@ def test_output_plot_kitchen(page: Page, app: ShinyAppProc) -> None:
 
     plot = OutputPlot(page, "p")
 
-    plot.expect_inline(inline=False)
+    plot.expect_inline(False)
     plot.expect_height("400px")
     plot.expect_width("100%")
 
diff --git a/tests/playwright/shiny/plot-sizing/test_plot_sizing.py b/tests/playwright/shiny/plot-sizing/test_plot_sizing.py
index cb9afc08b..ae1fa7664 100644
--- a/tests/playwright/shiny/plot-sizing/test_plot_sizing.py
+++ b/tests/playwright/shiny/plot-sizing/test_plot_sizing.py
@@ -41,7 +41,7 @@ def test_output_image_kitchen(page: Page, local_app: ShinyAppProc) -> None:
             img = OutputPlot(page, plotid)
             # These assertions are mostly to ensure that the plots load before we
             # evaluate their sizes
-            img.expect_inline(inline=False)
+            img.expect_inline(False)
             img.expect_img_src(re.compile(r"data:image/png;base64"), timeout=20000)
 
             rect = page.evaluate(