handy dialogs in/for svelte, see some examples
You can install via npm
npm i svelte-dialogs
or use jsdelivr CDN and add the script tag
<script src="https://cdn.jsdelivr.net/npm/svelte-dialogs"></script>
If so, follow the CDN script tag usage.
the easiest way to use svelte-dialog is
<script>
import { dialogs } from "svelte-dialogs";
</script>
<button on:click={() => dialogs.alert('this is an alert')}>click me</button>
dialogs
methods for rendering a dialog are:
alert()
shows a dialog with a dismiss buttonconfirm()
shows a dialog with a confirm and decline buttonprompt()
shows a dialog with inputs, a cancel, submit and an optional reset buttonmodal()
shows a modal with..... well, everything you want in it (or nothing, if called empty)error()
,success()
andwarning()
show accordingly styled alert. These are handy methods meant to be customized in configuration (or used as they are, if you like the default styles....)
all exepts for prompt()
can be called with an options parameter (see below) or with a string parameter (rendered as html):
alert()
andconfirm()
will use that as a titleerror()
,success()
andwarning()
will use that as text (title is meant to be the same for all of them)modal()
will use it as the whole content.
<script>
import { dialogs } from "svelte-dialogs";
/**
* When using custom modal content, use the default title id (dialog-title-id)
* or change the titleId options accordingly for accessibility reasons:
* titleId is used in aria-labelledby attribute
*/
const htmlString = `
<div>
<h1 id="dialog-title-id">all the html you want</h1>
<div style="text-align: center">
<p>now in text!</p>
</div>
</div>`;
</script>
<button on:click={() => dialogs.modal(htmlString)}>Click me!</button>
prompt()
accepts two parameters:
- a string/SvelteComponent/object or array of string/SvelteComponent/object parameter
- an options parameter (optional)
Using strings in first parameter, will result in inputs with that string as labels. Using objects, you can specify component and props to use as input. If you pass only props, the default input is used.
<script>
import { dialogs } from "svelte-dialogs";
</script>
<button on:click={() => dialogs.prompt("an input")}>click me</button>
<button on:click={() => dialogs.prompt(["an input", { label: "a required password input", type: "password", required: true }])}>click me</button>
You can use options with all the methods (see below) like so:
<script>
import { dialogs } from "svelte-dialogs";
const opts = {
title: "a title",
text: "the text",
titleClass: "my-title-class",
closeButton: false,
closeOnBg: true,
onShow: () => {
doSomething();
doSomethingElse();
}
transitions: {
in: {
transition: fade,
props: {
duration: 2000,
},
},
},
};
</script>
<button on:click={() => dialogs.modal(opts)}>click me</button>
<button on:click={() => dialogs.prompt("an input", opts)}>click me</button>
modal()
also can be called with a SvelteComponent parameter and an optional props parameter.
svelte-dialogs also exports a DialogContent
component with three styled optional slots (header, body and footer).
To retrieve the close function and options from the context, svelte-dialogs exports getClose()
and getOptions()
functions to be called at initialization.
So for example:
// MyComponent.svelte
<script>
import { DialogContent, getClose, getOptions } from "svelte-dialogs";
const close = getClose();
const {titleId} = getOptions();
export let name = "";
</script>
<DialogContent>
<h1 id={titleId} slot="header">My component</h1>
<svelte:fragment slot="body">
<p>hello {name}</p>
</svelte:fragment>
<svelte:fragment slot="footer">
<button on:click={() => close('!')}>close me</button>
</svelte:fragment>
</DialogContent>
// another component
<script>
import { dialogs } from "svelte-dialogs";
import MyComponent from "./MyComponent.svelte";
</script>
<button on:click={() => dialogs.modal(MyComponent, { name: "world" }).then(dialogs.alert)}>click me</button>
prompt()
accepts as first parameter, an object, or objects array, in the shape of {component: SvelteComponent, props: object}
.
// MyInput.svelte
<script>
export let value = '';
export let placeholder;
export let label;
export let name;
export let id;
</script>
<label for={id}>{label}</label>
<input bind:value {placeholder} {id} {name} type="text" />
// another component
<script>
import { dialogs } from "svelte-dialogs";
import MyInput from "./MyInput.svelte";
const myInputProps = {
placeholder: "a placeholder",
label: "my input",
name: "my-input",
id: "my-input-id",
};
</script>
<button
on:click={() =>
dialogs.prompt({
component: MyInput,
props: myInputProps,
})}
>click me</button>
If no prop is required, you can just pass the component as in prompt(MyInput)
All methods described return a promise that resolve on close:
alert()
resolveundefined
on dismissconfirm()
resolvestrue
on confirm,false
on decline andundefined
on dismissprompt()
resolvesundefined
on dismiss, while on submit resolves with an array of the inputs values
so you can do something like this:
<script>
import { dialogs } from "svelte-dialogs";
async function persistent() {
let confirm;
let times = "";
do {
confirm = await dialogs.confirm(
"are you" + times + " sure?"
);
times += " really";
} while (confirm);
dialogs.alert("well done......");
}
</script>
<button on:click={persistent}>persistent dialog</button>
It's possible to define and use modals in-component using the Dialog
component exported by svelte-dialogs that accept an options
props and emit:
show
on in-transition startshown
on in-transition endhide
on out-transition starthidden
on out-transition end
The component exports open()
that accepts data to be passed to the modal.
close
function and data
passed on open()
are passed to slot as props. close
accept a parameter that will be emitted by on:hide
The component also exports close()
and data()
methods to close and retrieve modal data outside the modal
<script>
import { Dialog } from "svelte-dialogs";
let dialog;
const titleId = "my-dialog-title";
const options = {
titleId,
closeButton: false,
closeOnBg: false,
closeOnEsc: false,
};
function handler({ type, detail }) {
// event.type 'hide' have event.detail === "my data"
console.log(type, detail);
}
</script>
<button on:click={() => dialog.open("my data")}>show</button>
<Dialog
bind:this={dialog}
on:show={handler}
on:shown={handler}
on:hide={handler}
on:hidden={handler}
let:data
let:close
{options}
>
<h1 id={titleId}>In-component events-based dialog</h1>
<p>{data}</p>
<button on:click={() => close(data)}>close</button>
</Dialog>
If you install svelte-dialogs via the script tag in a non-svelte project, the script adds the SvelteDialogs
global object which includes the same functions of the dialogs
export of the es module. You can use it like so:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>My App Title</title>
<script src="https://cdn.jsdelivr.net/npm/svelte-dialogs"></script>
</head>
<body>
<button id="btn" onclick="SvelteDialogs.alert('This dialog is imported via script tag')">
click me
</button>
</body>
</html>
You can configure the defaults with svelte-dialogs export config()
, for example in the entry point of you application or in you main component, like so:
// main.js
import App from "./App.svelte";
import { dialogs } from "svelte-dialogs";
dialogs.config({
global: {
overlayClass: "some-other-class",
dialogClass: "some-other-class",
closeButtonClass: "some-other-class",
closeButtonText: "close me",
headerClass: "some-other-class",
titleClass: "some-other-class",
bodyClass: "some-other-class",
footerClass: "some-other-class",
},
});
const app = new App({
target: document.body,
props: {},
});
export default app;
config accept an object with the following properties: global
, alert
, confirm
, error
, success
, warning
,and prompt
to fine-tuning the defaults at the beginning and then forget about it.
Every property is a config object as the one below.
It can obviously get confusing, but the order of importance for the options is:
call options -> configured per-method options -> configured global options -> defaults
.... have fun!
{
// sets the content of the dialog,
// overwriting the default component (that is DialogDontent)
content?: string | htmlString | SvelteComponent;
// props passed to the component
props?: object;
// these options always work, regardless of the component
closeButton?: boolean;
closeOnBg?: boolean;
closeOnEsc?: boolean;
transitions?: {
bgIn?: { transition: transition | string; props: object };
bgOut?: { transition: transition | string; props: object };
in?: { transition: transition | string; props: object };
out?: { transition: transition | string; props: object };
};
onHide: () => void;
onHidden: () => void;
onShow: () => void;
onShown: () => void;
overlayClass?: string;
dialogClass?: string;
closeButtonClass?: string;
closeButtonText?: string | htmlString;
// specific to DialogContent, use these if your component
// uses DialogContent or whith defaults
title?: string | htmlString;
text?: string | htmlString;
headerClass?: string;
titleClass?: string;
titleId?: string;
dividerClass?: string;
bodyClass?: string;
footerClass?: string;
// specific to alert() with default component
dismissButtonText?: string | htmlString;
dismissButtonClass?: string;
// specific to confirm() with default component
confirmButtonText?: string | htmlString;
declineButtonText?: string | htmlString;
confirmButtonClass?: string;
declineButtonClass?: string;
// specific to prompt() with default component
inputComponent?: SvelteComponent;
inputProps?: object;
resetButton?: boolean;
formClass?: string;
formElementClass?: string;
inputLabelClass?: string;
inputClass?: string;
submitButtonText?: string | htmlString;
cancelButtonText?: string | htmlString;
resetButtonText?: string | htmlString;
submitButtonClass?: string;
cancelButtonClass?: string;
resetButtonClass?: string;
}
The transitions
object defines in/out transitions for the background overlay and the dialog with their props. You can use custom transitions functions or the ones in the svelte/tansitions package. If you're using svelte-dialogs in a non-svelte project, you can pass these transitions as string, for example:
transitions: {
in: {
transition: 'slide',
props: {
duration: 2000,
},
},
}