Add content and target support for Alert component, then Alert can be used in uncontrolled mode like Popover.
<Alert content="Sure delete?" onConfirm={this.props.deleteSth}>
<Button text='Delete' />
</Alert>
Alert is specifically designed to be opinionated with restrictive interactions. In the meantime, try Dialog for a more controlled, flexible usage?
There was a proposal a while back to introduce Toaster-style imperative APIs for Dialog and Alert, which I prefer more than this Popover-style proposal.
Dialog.show({ ... }, () => { /* on close */ });
@giladgray can you point me to that proposal? I am looking for a way to do imperative dialogs/alerts with blueprint. Thanks!
@tnrich it was an internal issue, so unfortunately I can't share the conversation. but I wrote a sweet "promisify" Dialog wrapper recently that I'd be happy to share.
my ideal API looks something like this:
MyDialog.show(props?).then(result => handler)
Yep that seems like a pretty sweet api! I just wrote something similar to wrap Alert but it would be great to have for dialog, alert etc.
My api is a little more clunky:
<button
onClick={() => {
showConfirmationDialog({
text: "Are you sure you want to do that?",
onConfirm: () => {
console.log("proceed with action!");
}
});
}}
>
Do Dangerous Action
</button>
So if you could give me yours that would be great
@giladgray eh?
Hmm actually I just wrapped it in a promise. Haven't tested it yet but this should work just fine:
import React, { Component } from "react";
import { Alert, Intent } from "@blueprintjs/core";
import ReactDOM from "react-dom";
// usage
// const continue = await showConfirmationDialog({
// text:
// "Are you sure you want to re-run this tool? Downstream tools with linked outputs will need to be re-run as well!",
// });
// if (continue) do something!
//returns a promise that resolves with true or false depending on if the user cancels or not!
export default function showConfirmationDialog(opts) {
return new Promise(resolve => {
renderOnDoc(handleClose => {
return <AlertWrapper {...{ ...opts, handleClose, resolve }} />;
});
});
}
class AlertWrapper extends Component {
state = { isOpen: true };
render() {
const {
handleClose,
children,
text = "customize like -- {text: 'your text here'} ",
resolve,
cancelButtonText = "Cancel",
intent = Intent.PRIMARY,
...rest
} = this.props;
return (
<Alert
isOpen={this.state.isOpen}
intent={intent}
onCancel={() => {
handleClose();
this.setState({ isOpen: false });
resolve(false);
}}
cancelButtonText={cancelButtonText}
onConfirm={() => {
handleClose();
this.setState({ isOpen: false });
resolve(true);
}}
{...rest}
>
{children || text}
</Alert>
);
}
}
export function renderOnDoc(fn) {
const elemDiv = document.createElement("div");
elemDiv.style.cssText =
"position:absolute;width:100%;height:100%;top:0px;opacity:0.3;z-index:100;";
document.body.appendChild(elemDiv);
const handleClose = () => {
setTimeout(() => {
ReactDOM.unmountComponentAtNode(elemDiv);
document.body.removeChild(elemDiv);
});
};
return ReactDOM.render(fn(handleClose), elemDiv);
}
sorry @tnrich i missed this thread but my approach is basically what you showed above!
Most helpful comment
There was a proposal a while back to introduce
Toaster-style imperative APIs forDialogandAlert, which I prefer more than thisPopover-style proposal.