Call RSuite Modals like a boss.
npm install @rsuite/interactions@next --save
- Easy to call out
alert()
,confirm()
,prompt()
styles modals as you already know how. - Await their return values.
- Multiple calls are queued.
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');
}, []);
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. IfonOk
returns aPromise
, "OK" button shows loading status until the promise finishes.
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.');
}
}, []);
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 settrue
, "OK" button is red colored.cancelButtonText
: Customize "Cancel" button text.onOk
: Callback function when "OK" is clicked. IfonOk
returns aPromise
, "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
: WhenonCancel
is set, you can still use this option to force disable "Cancel" button.
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}.`);
}
}, []);
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 settrue
, "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. IfonOk
returns aPromise
, "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
: WhenonCancel
is set, you can still use this option to force disable "Cancel" button.inputProps
: custom input properties, learn more information aboutInputProps
from here
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?');
});
MIT licensed