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

Code before:
          <button
            type="button"
            id={button.id}
            class={buttonClass(button)}
            tabIndex={0}
            onClick={() => this.buttonClick(button)}
          >
            <span class="alert-button-inner">{button.text}</span>
            {mode === 'md' && <ion-ripple-effect></ion-ripple-effect>}
          </button>
        ))}
      </div>
    );
  }

  render() {
    const { overlayIndex, header, subHeader, message, htmlAttributes } = this;
    const mode = getIonMode(this);
    const hdrId = `alert-${overlayIndex}-hdr`;
    const subHdrId = `alert-${overlayIndex}-sub-hdr`;
    const msgId = `alert-${overlayIndex}-msg`;
    const role = this.inputs.length > 0 || this.buttons.length > 0 ? 'alertdialog' : 'alert';

    /**
     * If the header is defined, use that. Otherwise, fall back to the subHeader.
     * If neither is defined, don't set aria-labelled by.
     */
    const ariaLabelledBy = header ? hdrId : subHeader ? subHdrId : null;

    return (
      <Host
        role={role}
        aria-modal="true"
        aria-labelledby={ariaLabelledBy}
        aria-describedby={message ? msgId : null}
        tabindex="-1"
        {...(htmlAttributes as any)}
        style={{
          zIndex: `${20000 + overlayIndex}`,
        }}
        class={{
          ...getClassMap(this.cssClass),
          [mode]: true,
          'overlay-hidden': true,
          'alert-translucent': this.translucent,
        }}
        onIonAlertWillDismiss={this.dispatchCancelHandler}
        onIonBackdropTap={this.onBackdropTap}
      >
        <ion-backdrop tappable={this.backdropDismiss} />


Review comment (suggestion):
```suggestion
     * If neither is defined, don't set aria-labelledby.
```

Code after:
          <button
            type="button"
            id={button.id}
            class={buttonClass(button)}
            tabIndex={0}
            onClick={() => this.buttonClick(button)}
          >
            <span class="alert-button-inner">{button.text}</span>
            {mode === 'md' && <ion-ripple-effect></ion-ripple-effect>}
          </button>
        ))}
      </div>
    );
  }

  render() {
    const { overlayIndex, header, subHeader, message, htmlAttributes } = this;
    const mode = getIonMode(this);
    const hdrId = `alert-${overlayIndex}-hdr`;
    const subHdrId = `alert-${overlayIndex}-sub-hdr`;
    const msgId = `alert-${overlayIndex}-msg`;
    const role = this.inputs.length > 0 || this.buttons.length > 0 ? 'alertdialog' : 'alert';

    /**
     * If the header is defined, use that. Otherwise, fall back to the subHeader.
     * If neither is defined, don't set aria-labelledby.
     */
    const ariaLabelledBy = header ? hdrId : subHeader ? subHdrId : null;

    return (
      <Host
        role={role}
        aria-modal="true"
        aria-labelledby={ariaLabelledBy}
        aria-describedby={message ? msgId : null}
        tabindex="-1"
        {...(htmlAttributes as any)}
        style={{
          zIndex: `${20000 + overlayIndex}`,
        }}
        class={{
          ...getClassMap(this.cssClass),
          [mode]: true,
          'overlay-hidden': true,
          'alert-translucent': this.translucent,
        }}
        onIonAlertWillDismiss={this.dispatchCancelHandler}
        onIonBackdropTap={this.onBackdropTap}
      >
        <ion-backdrop tappable={this.backdropDismiss} />