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

Code before:
            if 'facecolor' in radio_props:
                _api.warn_external(
                    'Both the *activecolor* parameter and the *facecolor* '
                    'key in the *radio_props* parameter has been specified. '
                    '*activecolor* will be ignored.')
        else:
            activecolor = 'blue'  # Default.

        self._activecolor = activecolor
        self._initial_active = active
        self.value_selected = labels[active]
        self.index_selected = active

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

        self._useblit = useblit and self.canvas.supports_blit
        self._background = None

        label_props = _expand_text_props(label_props)

        # Calculate button and label positions
        button_xs, button_ys, label_xs, label_ys = _calculate_widget_button_layout(
            ax, labels, label_props, layout
        )

        self.labels = [
            ax.text(x, y, label, transform=ax.transAxes,
                    horizontalalignment="left", verticalalignment="center",
                    **props)
            for x, y, label, props in zip(label_xs, label_ys, labels, label_props)]
        text_size = np.array([text.get_fontsize() for text in self.labels]) / 2

        radio_props = {
            's': text_size**2,
            **radio_props,
            'marker': 'o',
            'transform': ax.transAxes,
            'animated': self._useblit,
        }
        radio_props.setdefault('edgecolor', radio_props.get('color', 'black'))
        radio_props.setdefault('facecolor',
                               radio_props.pop('color', activecolor))
        self._buttons = ax.scatter(button_xs, button_ys, **radio_props)
        # The user may have passed custom colours in radio_props, so we need to
        # create the radios, and modify the visibility after getting whatever
        # the user set.
        self._active_colors = self._buttons.get_facecolor()
        if len(self._active_colors) == 1:
            self._active_colors = np.repeat(self._active_colors, n_labels,

Review comment (performance):
```suggestion
            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
```
Let's be defensive, and reserve the rigt to fine-tune the algorithm.

Code after:
            The color of the selected button. The default is ``'blue'`` if not
            specified here or in *radio_props*.
        layout : None or "vertical" or "horizontal" or (int, int), default: None
            The layout of the radio buttons. Options are:

            - ``None``: Use legacy vertical layout (default).
            - ``"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)``
            create ``mtext.Text`` objects to determine exact text sizes, and
            then they are added to the Axes. This is usually okay, but may cause
            side-effects and has a slight performance impact. Therefore the
            default ``None`` value avoids this.

            .. admonition:: Provisional
                The new layout options are provisional. Their algorithmic
                behavior, including 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

        label_props : dict of lists, optional
            Dictionary of `.Text` properties to be used for the labels. Each
            dictionary value should be a list of at least a single element. If
            the list is of length M, its values are cycled such that the Nth
            label gets the (N mod M) property.

            .. versionadded:: 3.7
        radio_props : dict, optional
            Dictionary of scatter `.Collection` properties to be used for the
            radio buttons. Defaults to (label font size / 2)**2 size, black
            edgecolor, and *activecolor* facecolor (when active).

            .. note::
                If a facecolor is supplied in *radio_props*, it will override
                *activecolor*. This may be used to provide an active color per
                button.

            .. versionadded:: 3.7
        """