diff --git a/changelogs/upcoming/7576.md b/changelogs/upcoming/7576.md
new file mode 100644
index 00000000000..e5f340ead1d
--- /dev/null
+++ b/changelogs/upcoming/7576.md
@@ -0,0 +1 @@
+- Updated `EuiSuperUpdateButton` to support custom button text via an optional `children` prop
diff --git a/src-docs/src/views/super_date_picker/playground.js b/src-docs/src/views/super_date_picker/playground.js
index 610014ac214..8431a8f80fb 100644
--- a/src-docs/src/views/super_date_picker/playground.js
+++ b/src-docs/src/views/super_date_picker/playground.js
@@ -77,6 +77,11 @@ export const superUpdateButtonConfig = () => {
propsToUse.onClick = simulateFunction(propsToUse.onClick, true);
+ propsToUse.children = {
+ ...propsToUse.children,
+ type: PropTypes.String,
+ };
+
return {
config: {
componentName: 'EuiSuperUpdateButton',
diff --git a/src/components/date_picker/super_date_picker/__snapshots__/super_update_button.test.tsx.snap b/src/components/date_picker/super_date_picker/__snapshots__/super_update_button.test.tsx.snap
index fa792a8d48e..6fd392b27bd 100644
--- a/src/components/date_picker/super_date_picker/__snapshots__/super_update_button.test.tsx.snap
+++ b/src/components/date_picker/super_date_picker/__snapshots__/super_update_button.test.tsx.snap
@@ -1,495 +1,25 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`EuiSuperUpdateButton iconOnly 1`] = `
-
-
-
-
-
-
-
-
-
-
-
-
-`;
-
exports[`EuiSuperUpdateButton is rendered 1`] = `
-
-
-
-
-
-
-
-
-
-
-
-
-`;
-
-exports[`EuiSuperUpdateButton isDisabled 1`] = `
-
- }
- delay="regular"
- display="inlineBlock"
- position="bottom"
->
-
-
-
-
-
-
-
-
-
-
-
-`;
-
-exports[`EuiSuperUpdateButton isLoading 1`] = `
-
-
-
-
-
-
-
-
-
-
-
-
-`;
-
-exports[`EuiSuperUpdateButton needsUpdate 1`] = `
-
- }
- delay="regular"
- display="inlineBlock"
- position="bottom"
->
-
-
-
-
-
-
-
-
-
-
-
-`;
-
-exports[`EuiSuperUpdateButton responsive can be all 1`] = `
-
-
-
-
-
-
-
-
-
-
-
-
-`;
-
-exports[`EuiSuperUpdateButton responsive can be false 1`] = `
-
-
-
-
-
-
-
-
-
-
-
-
-`;
-
-exports[`EuiSuperUpdateButton showTooltip 1`] = `
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
`;
diff --git a/src/components/date_picker/super_date_picker/super_update_button.test.tsx b/src/components/date_picker/super_date_picker/super_update_button.test.tsx
index 6a606c49b59..a2cf931a92a 100644
--- a/src/components/date_picker/super_date_picker/super_update_button.test.tsx
+++ b/src/components/date_picker/super_date_picker/super_update_button.test.tsx
@@ -7,13 +7,12 @@
*/
import React from 'react';
-import { shallow, mount } from 'enzyme';
import { fireEvent } from '@testing-library/react';
-import { waitForEuiToolTipVisible } from '../../../test/rtl';
+import { render, waitForEuiToolTipVisible, within } from '../../../test/rtl';
import { shouldRenderCustomStyles } from '../../../test/internal';
import { EuiSuperUpdateButton } from './super_update_button';
-import { EuiButton, EuiButtonProps } from '../../button';
+import { EuiButtonProps } from '../../button';
const noop = () => {};
@@ -37,109 +36,120 @@ describe('EuiSuperUpdateButton', () => {
}
);
- test('is rendered', () => {
- const component = shallow();
-
- expect(component).toMatchSnapshot();
- });
-
- test('needsUpdate', () => {
- const component = shallow(
-
+ it('is rendered', () => {
+ const { container, getByRole } = render(
+
);
- expect(component).toMatchSnapshot();
- });
+ const tooltipWrapper = container.querySelector('.euiToolTipAnchor');
+ expect(tooltipWrapper).toBeInTheDocument();
- test('isDisabled', () => {
- const component = shallow(
-
- );
+ const button = getByRole('button');
+ expect(button).toBeInTheDocument();
+ expect(button).toHaveClass('euiSuperUpdateButton');
+ expect(button).toHaveTextContent('Refresh');
- expect(component).toMatchSnapshot();
+ expect(container).toMatchSnapshot();
});
- test('isLoading', () => {
- const component = shallow(
-
- );
+ describe('props', () => {
+ test('needsUpdate', () => {
+ const { getByRole } = render(
+
+ );
- expect(component).toMatchSnapshot();
- });
+ expect(getByRole('button')).toHaveTextContent('Update');
+ });
- test('iconOnly', () => {
- const component = shallow();
+ test('isDisabled', () => {
+ const { getByRole } = render(
+
+ );
- expect(component).toMatchSnapshot();
- });
+ expect(getByRole('button')).toBeDisabled();
+ });
- test('showTooltip', () => {
- const component = shallow(
-
- );
+ test('isLoading', () => {
+ const { getByRole } = render(
+
+ );
- expect(component).toMatchSnapshot();
- });
+ expect(getByRole('button')).toHaveTextContent('Updating');
- test('responsive can be all', () => {
- const component = shallow(
-
- );
+ const icon = getByRole('progressbar');
+ expect(icon).toHaveAccessibleName('Loading');
+ });
- expect(component).toMatchSnapshot();
- });
+ test('iconOnly', () => {
+ const { getByText, container } = render(
+
+ );
- test('responsive can be false', () => {
- const component = shallow(
-
- );
+ const icon = container.querySelector('[data-euiicon-type]');
+ expect(icon).toBeInTheDocument();
+ expect(icon).toHaveAttribute('data-euiicon-type', 'refresh');
- expect(component).toMatchSnapshot();
- });
+ const text = getByText('Refresh');
+ expect(text).toBeInTheDocument();
+ expect(text).toHaveClass('euiScreenReaderOnly');
+ });
- test('forwards props to EuiButton', () => {
- const speciallyHandledProps = {
- className: 'testClass',
- textProps: {
- className: 'textPropsTestClass',
- id: 'test',
- },
- };
- const extraProps: Partial = {
- fill: false,
- size: 's',
- contentProps: { id: 'contentSpan' },
- };
-
- const component = mount(
- {}}
- {...speciallyHandledProps}
- {...extraProps}
- />
- );
+ test('showTooltip', () => {
+ const { container } = render(
+
+ );
- const {
- // props not passed through
- isDisabled,
- isLoading,
- onClick,
+ const tooltipWrapper = container.querySelector('.euiToolTipAnchor');
+ expect(tooltipWrapper).toBeInTheDocument();
+ });
- // props with special handling
- className,
- textProps,
+ test('children', () => {
+ const { getByRole } = render(
+
+
+
+ );
- ...forwardedProps
- } = component.find(EuiButton).props();
+ const button = getByRole('button');
+ expect(button).toHaveTextContent('');
+
+ const customChildren = within(button).getByTestSubject('custom-children');
+ expect(customChildren).toBeInTheDocument();
+ });
- expect(className).toBe('euiSuperUpdateButton testClass');
- expect(textProps).toEqual({
- className: 'textPropsTestClass',
- id: 'test',
+ it('forwards props to EuiButton', () => {
+ const speciallyHandledProps = {
+ className: 'testClass',
+ textProps: {
+ className: 'textPropsTestClass',
+ id: 'test',
+ 'data-test-subj': 'text',
+ },
+ };
+ const extraProps: Partial = {
+ fill: false,
+ size: 's',
+ contentProps: { id: 'contentSpan', 'data-test-subj': 'content' },
+ };
+
+ const { getByRole, getByTestSubject } = render(
+ {}}
+ {...speciallyHandledProps}
+ {...extraProps}
+ />
+ );
+
+ const button = getByRole('button');
+ expect(button).toHaveClass('testClass');
+
+ const text = getByTestSubject('text');
+ expect(text).toBeInTheDocument();
+ expect(text).toHaveAttribute('id', 'test');
+ expect(text).toHaveClass('textPropsTestClass');
+
+ const buttonContent = within(button).getByTestSubject('content');
+ expect(buttonContent).toBeInTheDocument();
});
- expect(forwardedProps).toMatchObject(extraProps);
});
});
diff --git a/src/components/date_picker/super_date_picker/super_update_button.tsx b/src/components/date_picker/super_date_picker/super_update_button.tsx
index 8c67f437ca8..58d7687e251 100644
--- a/src/components/date_picker/super_date_picker/super_update_button.tsx
+++ b/src/components/date_picker/super_date_picker/super_update_button.tsx
@@ -6,7 +6,12 @@
* Side Public License, v 1.
*/
-import React, { Component, MouseEventHandler, ElementRef } from 'react';
+import React, {
+ Component,
+ MouseEventHandler,
+ ElementRef,
+ ReactNode,
+} from 'react';
import classNames from 'classnames';
import { EuiButton, EuiButtonProps } from '../../button';
@@ -25,6 +30,15 @@ type EuiSuperUpdateButtonInternalProps = {
};
export type EuiSuperUpdateButtonProps = {
+ /**
+ * Overrides the default button label with a custom React node.
+ *
+ * When defined, you're responsible for updating the custom label
+ * when the data needs updating (the `needsUpdate` prop)
+ * or is loading (the `isLoading` prop).
+ */
+ children?: ReactNode;
+
/**
* Show the "Click to apply" tooltip
*/
@@ -45,7 +59,9 @@ export type EuiSuperUpdateButtonProps = {
* Remove completely with `false` or provide your own list of breakpoints.
*/
responsive?: false | EuiBreakpointSize[];
-} & Partial>;
+} & Partial<
+ Omit
+>;
export class EuiSuperUpdateButton extends Component<
EuiSuperUpdateButtonInternalProps & EuiSuperUpdateButtonProps
@@ -104,6 +120,7 @@ export class EuiSuperUpdateButton extends Component<
render() {
const {
+ children,
className,
needsUpdate,
isLoading,
@@ -122,43 +139,6 @@ export class EuiSuperUpdateButton extends Component<
const classes = classNames('euiSuperUpdateButton', className);
- let buttonText = (
-
- );
- if (needsUpdate || isLoading) {
- buttonText = isLoading ? (
-
- ) : (
-
- );
- }
-
- let tooltipContent;
- if (isDisabled) {
- tooltipContent = (
-
- );
- } else if (needsUpdate && !isLoading) {
- tooltipContent = (
-
- );
- }
-
const sharedButtonProps = {
color: needsUpdate || isLoading ? 'success' : 'primary',
iconType: needsUpdate || isLoading ? 'kqlFunction' : 'refresh',
@@ -167,10 +147,12 @@ export class EuiSuperUpdateButton extends Component<
isLoading: isLoading,
};
+ const buttonContent = this.renderButtonContent();
+
return (
@@ -190,7 +172,7 @@ export class EuiSuperUpdateButton extends Component<
}}
{...rest}
>
- {buttonText}
+ {buttonContent}
@@ -202,11 +184,64 @@ export class EuiSuperUpdateButton extends Component<
textProps={restTextProps}
{...rest}
>
- {buttonText}
+ {buttonContent}
>
);
}
+
+ private renderButtonContent(): ReactNode {
+ const { children, isLoading, needsUpdate } = this.props;
+
+ if (children) {
+ return children;
+ }
+
+ if (isLoading) {
+ return (
+
+ );
+ }
+
+ if (needsUpdate) {
+ return (
+
+ );
+ }
+
+ return (
+
+ );
+ }
+
+ private renderTooltipContent(): ReactNode {
+ if (this.props.isDisabled) {
+ return (
+
+ );
+ }
+
+ if (this.props.needsUpdate && !this.props.isLoading) {
+ return (
+
+ );
+ }
+ }
}