Repository: ionic-team/ionic-framework
File: core/src/components/action-sheet/action-sheet.tsx (TypeScript)

Code before:
  /**
   * If `true`, the keyboard will be automatically dismissed when the overlay is presented.
   */
  @Prop() keyboardClose = true;

  /**
   * Animation to use when the action sheet is presented.
   */
  @Prop() enterAnimation?: AnimationBuilder;

  /**
   * Animation to use when the action sheet is dismissed.
   */
  @Prop() leaveAnimation?: AnimationBuilder;

  /**
   * An array of buttons for the action sheet.
   */
  @Prop() buttons: (ActionSheetButton | string)[] = [];
  @Watch('buttons')
  buttonsChanged() {
    // Initialize activeRadioId when buttons change
    if (this.hasRadioButtons) {
      const allButtons = this.getButtons();
      const radioButtons = this.getRadioButtons();
      const checkedButton = radioButtons.find((b) => b.htmlAttributes?.['aria-checked'] === 'true');
      if (checkedButton) {
        const checkedIndex = allButtons.indexOf(checkedButton);
        this.activeRadioId = this.getButtonId(checkedButton, checkedIndex);
      }
    }
  }

  /**
   * Additional classes to apply for custom CSS. If multiple classes are
   * provided they should be separated by spaces.
   */
  @Prop() cssClass?: string | string[];

  /**
   * If `true`, the action sheet will be dismissed when the backdrop is clicked.
   */
  @Prop() backdropDismiss = true;

  /**
   * Title for the action sheet.
   */
  @Prop() header?: string;

  /**
   * Subtitle for the action sheet.

Review comment (bug):
My only concern here is `this.hasRadioButtons` is only set in `connectedCallback`, I believe this means if buttons are set dynamically this value may become stale and this process may not trigger when it's supposed to. That's sort of an edge case for many, but it may be worth re-computing `this.hasRadioButtons` here, if you feel like this could be a concern. Up to you!

Code after:
  /**
   * If `true`, the keyboard will be automatically dismissed when the overlay is presented.
   */
  @Prop() keyboardClose = true;

  /**
   * Animation to use when the action sheet is presented.
   */
  @Prop() enterAnimation?: AnimationBuilder;

  /**
   * Animation to use when the action sheet is dismissed.
   */
  @Prop() leaveAnimation?: AnimationBuilder;

  /**
   * An array of buttons for the action sheet.
   */
  @Prop() buttons: (ActionSheetButton | string)[] = [];
  @Watch('buttons')
  buttonsChanged() {
    const radioButtons = this.getRadioButtons();
    this.hasRadioButtons = radioButtons.length > 0;

    // Initialize activeRadioId when buttons change
    if (this.hasRadioButtons) {
      const checkedButton = radioButtons.find((b) => b.htmlAttributes?.['aria-checked'] === 'true');

      if (checkedButton) {
        const allButtons = this.getButtons();
        const checkedIndex = allButtons.indexOf(checkedButton);
        this.activeRadioId = this.getButtonId(checkedButton, checkedIndex);
      }
    }
  }

  /**
   * Additional classes to apply for custom CSS. If multiple classes are
   * provided they should be separated by spaces.
   */
  @Prop() cssClass?: string | string[];

  /**
   * If `true`, the action sheet will be dismissed when the backdrop is clicked.
   */
  @Prop() backdropDismiss = true;

  /**
   * Title for the action sheet.
   */
  @Prop() header?: string;