Repository: matplotlib/matplotlib
File: lib/matplotlib/widgets.py (Python)

Code before:
    ----------
    ax : `~matplotlib.axes.Axes`
        The parent Axes for the widget.
    labels : list of `~matplotlib.text.Text`
        The text label objects of the check buttons.
    """

    def __init__(self, ax, labels, actives=None, *, layout=None, useblit=True,
                 label_props=None, frame_props=None, check_props=None):
        """
        Add check buttons to `~.axes.Axes` instance *ax*.

        Parameters
        ----------
        ax : `~matplotlib.axes.Axes`
            The parent Axes for the widget.
        labels : list of str
            The labels of the check buttons.
        actives : list of bool, optional
            The initial check states of the buttons. The list must have the
            same length as *labels*. If not given, all buttons are unchecked.
        layout : None or "vertical" or "horizontal" or (int, int), default: None
            The layout of the check buttons. Options are:

            - ``None``: Use legacy vertical layout (default, keeps backward
              compatibility with fixed button and label positions).
            - ``"vertical"``: Arrange buttons in a single column with
              dynamic positioning based on text widths.
            - ``"horizontal"``: Arrange buttons in a single row with
              dynamic positioning based on text widths.
            - ``(rows, cols)`` tuple: Arrange buttons in a grid with the
              specified number of rows and columns. Buttons are placed
              left-to-right, top-to-bottom with dynamic positioning.

            The layout options "vertical", "horizontal" and ``(rows, cols)``
            temporarily manipulate the figure and redraw to determine
            exact text sizes. This is usually ok, but may cause side-effects
            and has a slight performance impact.

            .. admonition:: Provisional
                The the new layout options are provisional. Their algorithmic
                behavior, including if and when a figure redraw happens, as well
                as the the exact positions of buttons and labels may still change
                without prior warning.

            .. versionadded:: 3.11
        useblit : bool, default: True
            Use blitting for faster drawing if supported by the backend.
            See the tutorial :ref:`blitting` for details.

            .. versionadded:: 3.7

Review comment (suggestion):
```suggestion
            - ``None``: Use legacy vertical layout (default)
```
I think the note about backward compatibility should maybe be a standalone note/ at the bottom with the other layout notes. 

Code after:
                 **kwargs):
        super().__init__(ax)

        ax.set_xticks([])
        ax.set_yticks([])
        ax.set_navigate(False)

        self._useblit = useblit

        self._init_layout(layout, labels, label_props)
        text_size = np.array([text.get_fontsize() for text in self.labels]) / 2

        self._init_props(text_size, **kwargs)

        self.connect_event('button_press_event', self._clicked)
        if self._useblit:
            self.connect_event('draw_event', self._clear)

        self._observers = cbook.CallbackRegistry(signals=["clicked"])

    def _init_layout(self, layout, labels, label_props):

        label_props = _expand_text_props(label_props)

        if layout is None:
            # legacy hard-coded vertical layout
            self._buttons_xs = [0.15] * len(labels)
            self._buttons_ys = np.linspace(1, 0, len(labels)+2)[1:-1]
            self.labels = [
                self.ax.text(0.25, y, label, transform=self.ax.transAxes,
                        horizontalalignment="left", verticalalignment="center",
                        **props)
                for y, label, props in zip(self._buttons_ys, labels, label_props)]
            return

        # New layout algorithm with text measurement
        # Parse layout parameter
        n_labels = len(labels)
        match layout:
            case "vertical":
                n_rows, n_cols = n_labels, 1
            case "horizontal":
                n_rows, n_cols = 1, n_labels
            case (int() as n_rows, int() as n_cols):
                if n_rows * n_cols < n_labels:
                    raise ValueError(
                        f"layout {layout} has {n_rows * n_cols} positions but "
                        f"{n_labels} labels were provided"
                    )
            case _:
                raise ValueError(