ConfirmButton: Attach `onClick` to custom child button to better support a11y (#70504)

* change ConfirmButton to accept a function as a child so it can pass onClick to a custom child button

* spread button props instead

* update documentation

* remove duplicate line

* spread ref instead of className

* use cloneElement instead
pull/70906/head
Ashley Harrison 2 years ago committed by GitHub
parent 9ee2cc742a
commit cc794b884e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 18
      packages/grafana-ui/src/components/ConfirmButton/ConfirmButton.mdx
  2. 25
      packages/grafana-ui/src/components/ConfirmButton/ConfirmButton.tsx

@ -29,4 +29,22 @@ Apart from the button variant, you can also modify the button size and the butto
</ConfirmButton>
```
## With a custom button
You can pass a custom button as a child to the `ConfirmButton`. The child will automatically receive the correct `onClick` from `ConfirmButton`.
```jsx
<ConfirmButton
closeOnConfirm
size="md"
confirmText="Are you sure?"
confirmVariant="secondary"
onConfirm={() => {
console.log('Action confirmed!');
}}
>
<Button variant="secondary">Click me</Button>
</ConfirmButton>
```
<ArgTypes of={ConfirmButton} />

@ -1,5 +1,5 @@
import { cx, css } from '@emotion/css';
import React, { PureComponent, SyntheticEvent } from 'react';
import React, { PureComponent, ReactElement } from 'react';
import { GrafanaTheme2 } from '@grafana/data';
@ -11,6 +11,7 @@ import { Button, ButtonVariant } from '../Button';
export interface Props extends Themeable2 {
/** Confirm action callback */
onConfirm(): void;
children: string | ReactElement;
/** Custom button styles */
className?: string;
/** Button size */
@ -36,14 +37,14 @@ interface State {
showConfirm: boolean;
}
class UnThemedConfirmButton extends PureComponent<React.PropsWithChildren<Props>, State> {
class UnThemedConfirmButton extends PureComponent<Props, State> {
mainButtonRef = React.createRef<HTMLButtonElement>();
confirmButtonRef = React.createRef<HTMLButtonElement>();
state: State = {
showConfirm: false,
};
onClickButton = (event: SyntheticEvent) => {
onClickButton = (event: React.MouseEvent<HTMLButtonElement>) => {
if (event) {
event.preventDefault();
}
@ -64,7 +65,7 @@ class UnThemedConfirmButton extends PureComponent<React.PropsWithChildren<Props>
}
};
onClickCancel = (event: SyntheticEvent) => {
onClickCancel = (event: React.MouseEvent<HTMLButtonElement>) => {
if (event) {
event.preventDefault();
}
@ -80,7 +81,7 @@ class UnThemedConfirmButton extends PureComponent<React.PropsWithChildren<Props>
this.props.onCancel();
}
};
onConfirm = (event: SyntheticEvent) => {
onConfirm = (event: React.MouseEvent<HTMLButtonElement>) => {
if (event) {
event.preventDefault();
}
@ -118,17 +119,15 @@ class UnThemedConfirmButton extends PureComponent<React.PropsWithChildren<Props>
return (
<span className={styles.buttonContainer}>
<div className={cx(disabled && styles.disabled)}>
{typeof children === 'string' ? (
<span className={buttonClass}>
<span className={buttonClass}>
{typeof children === 'string' ? (
<Button size={size} fill="text" onClick={onClick} ref={this.mainButtonRef}>
{children}
</Button>
</span>
) : (
<span className={buttonClass} onClick={onClick}>
{children}
</span>
)}
) : (
React.cloneElement(children, { onClick, ref: this.mainButtonRef })
)}
</span>
</div>
<span className={confirmButtonClass}>
<Button size={size} variant={confirmButtonVariant} onClick={this.onConfirm} ref={this.confirmButtonRef}>

Loading…
Cancel
Save