Skip to content

rsuite/interactions

Repository files navigation

RSuite Interactions

Call RSuite Modals like a boss.

npm GitHub Actions codecov

npm install @rsuite/interactions@next --save

Features

  • Easy to call out alert(), confirm(), prompt() styles modals as you already know how.
  • Await their return values.
  • Multiple calls are queued.

API

alert

Use it like you are using window.alert(), and you can await it.

const buyNewPhone = useCallback(async () => {
  await alert("Congrats! You've got a new iPhone!");
  console.log('alert closed');
}, []);

Signatures

alert(
  message?: React.ReactNode,
  modalConfig?: AlertModalProps
): Promise<void>;

interface WrappedModalProps {
  modalProps: ModalProps;
}

interface AlertModalProps extends WrappedModalProps {
  okButtonText?: string;
  onOk?: (() => void) | (() => Promise<any>);
}
  • okButtonText: Customize "OK" button text.
  • onOk: Callback function when "OK" is clicked. If onOk returns a Promise, "OK" button shows loading status until the promise finishes.

confirm

Use it like you are using window.confirm() but await its return value.

const confirmSmashPhone = useCallback(async () => {
  if (await confirm('Are you sure you what to do this?')) {
    alert('Rest in pieces.');
  }
}, []);

Signatures

confirm(
  message?: React.ReactNode,
  modalConfig?: ConfirmModalProps
): Promise<boolean>;

interface WrappedModalProps {
  modalProps: ModalProps;
}
interface ConfirmModalProps extends WrappedModalProps {
  okButtonText?: string;
  okButtonDangerous?: boolean;
  cancelButtonText?: string;
  onOk?: (() => void) | (() => Promise<any>);
  onCancel?: (isSubmitLoading?: boolean) => any;
  canCancelOnLoading?: boolean;
}
  • okButtonText: Customize "OK" button text.
  • okButtonDangerous: When set true, "OK" button is red colored.
  • cancelButtonText: Customize "Cancel" button text.
  • onOk: Callback function when "OK" is clicked. If onOk returns a Promise, "OK" button shows loading status until the promise finishes.
  • onCancel: Callback function when "Cancel" is clicked. If not provided, "Cancel" is disabled when "OK" is loading.
  • canCancelOnLoading: When onCancel is set, you can still use this option to force disable "Cancel" button.

prompt

Use it like you are using window.prompt() but await its return value.

const promptForName = useCallback(async () => {
  const name = await prompt('What is your name?');
  if (name) {
    alert(`It\'s ok, ${name}.`);
  }
}, []);

Signatures

prompt(
  message?: React.ReactNode,
  _default?: string,
  modalConfig?: PromptModalProps
): Promise<string | null>;

interface WrappedModalProps {
  modalProps: ModalProps;
}
interface PromptModalProps extends WrappedModalProps {
  okButtonText?: string;
  okButtonDangerous?: boolean;
  cancelButtonText?: string;
  validate?: (inputValue: string) => boolean;
  onOk?: ((inputVal?: string) => void) | ((inputVal: string) => Promise<any>);
  onCancel?: (isSubmitLoading?: boolean) => any;
  canCancelOnLoading?: boolean;
  inputProps?: InputProps;
}
  • okButtonText: Customize "OK" button text.
  • okButtonDangerous: When set true, "OK" button is red colored.
  • cancelButtonText: Customize "Cancel" button text.
  • validate: Validate current input value. Disable OK button if validation fails.
  • onOk: Callback function when "OK" is clicked, receiving a string representing the user input. If onOk returns a Promise, "OK" button shows loading status until the promise finishes.
  • onCancel: Callback function when "Cancel" is clicked. If not provided, "Cancel" is disabled when "OK" is loading.
  • canCancelOnLoading: When onCancel is set, you can still use this option to force disable "Cancel" button.
  • inputProps: custom input properties, learn more information about InputProps from here

Testing

If you use @rsuite/interactions to call alert dialogs in your app, you can easily test it with @testing-library/react.

Say you want to show a confirm dialog when user clicks a button that will delete a post:

import { confirm } from '@rsuite/interactions';

function App() {
  async function confirmDeletePost(id) {
    if (await confirm('Are you sure?')) {
      await api.deletePost(id);
    }
  }

  return <button onClick={() => confirmDeletePost(1)}>Delete post 1</button>;
}

And you want to test that the dialog is shown when the button is clicked:

import { render, fireEvent, screen } from '@testing-library/react';

it('Should show a confirm dialog', () => {
  const { getByRole } = render(<App />);

  fireEvent.click(getByRole('button', { name: /delete post/i }));

  // Assume you're using Jest with @testing-library/jest-dom
  const dialog = screen.getByRole('alertdialog');
  expect(dialog).toBeVisible();
  // Assert on its a11y description
  expect(dialog).toHaveAccessibleDescription('Are you sure?');
  // Or if you're using jest-dom < 5.14, you can assert on its textContent
  expect(dialog).toHaveTextContent('Are you sure?');
});

License

MIT licensed