Modal
Default
<script>
import { Button, Modal, P } from "flowbite-svelte";
let defaultModal = $state(false);
</script>
<Button onclick={() => (defaultModal = true)}>Default modal</Button>
<Modal title="Terms of Service" form bind:open={defaultModal} onaction={({ action }) => alert(`Handle "${action}"`)}>
<P>With less than a month to go before the European Union enacts new consumer privacy laws for its citizens, companies around the world are updating their terms of service agreements to comply.</P>
<P>The European Union’s General Data Protection Regulation (G.D.P.R.) goes into effect on May 25 and is meant to ensure a common set of data rights in the European Union. It requires organizations to notify users as soon as possible of high-risk data breaches that could personally affect them.</P>
{#snippet footer()}
<Button type="submit" value="success">I accept</Button>
<Button type="submit" value="decline" color="alternative">Decline</Button>
{/snippet}
</Modal>
Pop-up modal
<script>
import { Button, Modal, P } from "flowbite-svelte";
import { ExclamationCircleOutline } from "flowbite-svelte-icons";
import { slide } from "svelte/transition";
let popupModal = $state(false);
</script>
<Button onclick={() => (popupModal = true)}>Pop-up modal</Button>
<Modal form bind:open={popupModal} size="xs" transition={slide} permanent>
<div class="text-center">
<ExclamationCircleOutline class="mx-auto mb-4 h-12 w-12 text-gray-400 dark:text-gray-200" />
<h3 class="mb-5 text-lg font-normal text-gray-500 dark:text-gray-400">Are you sure you want to delete this product?</h3>
<div class="space-x-2">
<Button type="submit" value="yes" color="red">Yes, I'm sure</Button>
<Button type="submit" value="no" color="alternative">No, cancel</Button>
</div>
</div>
</Modal>
Form element
<script lang="ts">
import { Button, Modal, Label, Input, Checkbox } from "flowbite-svelte";
let formModal = $state(false);
let error = $state("");
function onaction({ action, data }: { action: string; data: FormData }) {
error = "";
// Check the data validity, return false to prevent dialog closing; anything else to proceed
if (action === "login" && (data.get("password") as string)?.length < 4) {
error = "Password must have at least 4 characters";
return false;
}
}
</script>
<Button onclick={() => (formModal = true)}>Form modal</Button>
<Modal form bind:open={formModal} size="xs" {onaction}>
<div class="flex flex-col space-y-6">
<h3 class="mb-4 text-xl font-medium text-gray-900 dark:text-white">Sign in to our platform</h3>
{#if error}
<Label color="red">{error}</Label>
{/if}
<Label class="space-y-2">
<span>Email</span>
<Input type="email" name="email" placeholder="name@company.com" required />
</Label>
<Label class="space-y-2">
<span>Your password</span>
<Input type="password" name="password" placeholder="min. 4 characters" required />
</Label>
<div class="flex items-start">
<Checkbox name="remember">Remember me</Checkbox>
<a href="/" class="text-primary-700 dark:text-primary-500 ms-auto text-sm hover:underline">Lost password?</a>
</div>
<Button type="submit" value="login">Login to your account</Button>
<div class="text-sm font-medium text-gray-500 dark:text-gray-300">
Not registered? <a href="/" class="text-primary-700 dark:text-primary-500 hover:underline">Create account</a>
</div>
</div>
</Modal>
Crypto wallet
<script>
import { Button, Modal, Label, Input, Checkbox, P } from "flowbite-svelte";
import MetaMask from "../../../../utils/icons/MetaMask.svelte";
import CoinbaseWallet from "../../../../utils/icons/CoinbaseWallet.svelte";
import OperaWallet from "../../../../utils/icons/OperaWallet.svelte";
import Fortmatic from "../../../../utils/icons/Fortmatic.svelte";
import WalletConnect from "../../../../utils/icons/WalletConnect.svelte";
import { QuestionCircleOutline } from "flowbite-svelte-icons";
let walletModal = $state(false);
</script>
<Button onclick={() => (walletModal = true)}>Crypto wallet modal</Button>
<Modal title="Connect wallet" bind:open={walletModal} size="xs">
<P class="text-sm font-normal text-gray-500 dark:text-gray-400">Connect with one of our available wallet providers or create a new one.</P>
<ul class="my-4 space-y-3">
<li>
<a href="/" class="group flex items-center rounded-lg bg-gray-50 p-3 text-base font-bold text-gray-900 hover:bg-gray-100 hover:shadow-sm dark:bg-gray-600 dark:text-white dark:hover:bg-gray-500">
<MetaMask />
<span class="ms-3 flex-1 whitespace-nowrap">MetaMask</span>
<span class="ms-3 inline-flex items-center justify-center rounded-sm bg-gray-200 px-2 py-0.5 text-xs font-medium text-gray-500 dark:bg-gray-700 dark:text-gray-400">Popular</span>
</a>
</li>
<li>
<a href="/" class="group flex items-center rounded-lg bg-gray-50 p-3 text-base font-bold text-gray-900 hover:bg-gray-100 hover:shadow-sm dark:bg-gray-600 dark:text-white dark:hover:bg-gray-500">
<CoinbaseWallet />
<span class="ms-3 flex-1 whitespace-nowrap">Coinbase Wallet</span>
</a>
</li>
<li>
<a href="/" class="group flex items-center rounded-lg bg-gray-50 p-3 text-base font-bold text-gray-900 hover:bg-gray-100 hover:shadow-sm dark:bg-gray-600 dark:text-white dark:hover:bg-gray-500">
<OperaWallet />
<span class="ms-3 flex-1 whitespace-nowrap">Opera Wallet</span>
</a>
</li>
<li>
<a href="/" class="group flex items-center rounded-lg bg-gray-50 p-3 text-base font-bold text-gray-900 hover:bg-gray-100 hover:shadow-sm dark:bg-gray-600 dark:text-white dark:hover:bg-gray-500">
<WalletConnect />
<span class="ms-3 flex-1 whitespace-nowrap">WalletConnect</span>
</a>
</li>
<li>
<a href="/" class="group flex items-center rounded-lg bg-gray-50 p-3 text-base font-bold text-gray-900 hover:bg-gray-100 hover:shadow-sm dark:bg-gray-600 dark:text-white dark:hover:bg-gray-500">
<Fortmatic />
<span class="ms-3 flex-1 whitespace-nowrap">Fortmatic</span>
</a>
</li>
</ul>
<div>
<a href="/" class="inline-flex items-center text-xs font-normal text-gray-500 hover:underline dark:text-gray-400">
<QuestionCircleOutline class="me-2 h-3 w-3" /> Why do I need to connect with my wallet?
</a>
</div>
</Modal>
Clicking outside
<script>
import { Button, Modal, P } from "flowbite-svelte";
let open = $state(false);
</script>
<Button onclick={() => (open = true)}>Default modal</Button>
<Modal form bind:open outsideclose={false} class="backdrop:bg-red-900/50 dark:backdrop:bg-green-300/50">
{#snippet header()}
<h3>
Terms of Service <small class="font-normal">(Revised)</small>
</h3>
{/snippet}
<P>With less than a month to go before the European Union enacts new consumer privacy laws for its citizens, companies around the world are updating their terms of service agreements to comply.</P>
<P>The European Union’s General Data Protection Regulation (G.D.P.R.) goes into effect on May 25 and is meant to ensure a common set of data rights in the European Union. It requires organizations to notify users as soon as possible of high-risk data breaches that could personally affect them.</P>
{#snippet footer()}
<Button type="submit" value="accept">I accept</Button>
<Button type="submit" color="alternative">Decline</Button>
{/snippet}
</Modal>
Focus trap
<script lang="ts">
import { Button, Modal, Label, Input, Checkbox } from "flowbite-svelte";
let open = $state(false);
let checked = $state(false);
</script>
<Button onclick={() => (open = true)}>Default modal</Button>
<Checkbox bind:checked>Focus trap</Checkbox>
<Modal form bind:open focustrap={checked} size="sm" title="Notify user">
<Label class="space-y-2">
<span>Email:</span>
<Input autofocus />
</Label>
{#snippet footer()}
<Button type="submit" value="notify">Notify</Button>
<Button type="submit" color="alternative">Cancel</Button>
{/snippet}
</Modal>
Sizes
<script lang="ts">
import { Button, Modal, type ModalProps, P } from "flowbite-svelte";
let openModal = $state(false);
let size: ModalProps["size"] = $state("md"); // Set default value
function onclick(modalSize: ModalProps["size"]) {
size = modalSize;
openModal = true;
}
</script>
<div class="block space-y-4 md:space-y-0 md:space-x-4 rtl:space-x-reverse">
<Button onclick={() => onclick("xs")}>xs</Button>
<Button onclick={() => onclick("sm")}>sm</Button>
<Button onclick={() => onclick("md")}>md</Button>
<Button onclick={() => onclick("lg")}>lg</Button>
<Button onclick={() => onclick("xl")}>xl</Button>
</div>
<Modal form title="Terms of Service" bind:open={openModal} {size}>
<P>With less than a month to go before the European Union enacts new consumer privacy laws for its citizens, companies around the world are updating their terms of service agreements to comply.</P>
<P>The European Union’s General Data Protection Regulation (G.D.P.R.) goes into effect on May 25 and is meant to ensure a common set of data rights in the European Union. It requires organizations to notify users as soon as possible of high-risk data breaches that could personally affect them.</P>
{#snippet footer()}
<Button type="submit">I accept</Button>
<Button type="submit" color="alternative">Decline</Button>
{/snippet}
</Modal>
Placement
<script lang="ts">
import { Button, Modal, P } from "flowbite-svelte";
type ModalPlacementType = "top-left" | "top-center" | "top-right" | "center-left" | "center" | "center-right" | "bottom-left" | "bottom-center" | "bottom-right";
let placement: ModalPlacementType = $state("center");
let openPlacement = $state(false);
const setPlacement = (newPlacement: ModalPlacementType) => {
placement = newPlacement;
console.log("placement: ", placement);
openPlacement = !openPlacement;
};
</script>
<div class="inline-grid grid-cols-3 grid-rows-3 gap-4">
<Button onclick={() => setPlacement("top-left")}>top-left</Button>
<Button onclick={() => setPlacement("top-center")}>top-center</Button>
<Button onclick={() => setPlacement("top-right")}>top-right</Button>
<Button onclick={() => setPlacement("center-left")}>center-left</Button>
<Button onclick={() => setPlacement("center")}>center</Button>
<Button onclick={() => setPlacement("center-right")}>center-right</Button>
<Button onclick={() => setPlacement("bottom-left")}>bottom-left</Button>
<Button onclick={() => setPlacement("bottom-center")}>bottom-center</Button>
<Button onclick={() => setPlacement("bottom-right")}>bottom-right</Button>
</div>
<Modal title="Terms of Service" form bind:open={openPlacement} {placement}>
<P>With less than a month to go before the European Union enacts new consumer privacy laws for its citizens, companies around the world are updating their terms of service agreements to comply.</P>
<P>The European Union’s General Data Protection Regulation (G.D.P.R.) goes into effect on May 25 and is meant to ensure a common set of data rights in the European Union. It requires organizations to notify users as soon as possible of high-risk data breaches that could personally affect them.</P>
{#snippet footer()}
<Button type="submit">I accept</Button>
<Button type="submit" color="alternative">Decline</Button>
{/snippet}
</Modal>
Scrolling behaviour
<script>
import { Button, Modal, P } from "flowbite-svelte";
let scrollingModal = $state(false);
</script>
<Button onclick={() => (scrollingModal = true)}>Scrolling modal</Button>
<Modal title="Terms of Service" form bind:open={scrollingModal}>
<P>With less than a month to go before the European Union enacts new consumer privacy laws for its citizens, companies around the world are updating their terms of service agreements to comply.</P>
<P>The European Union’s General Data Protection Regulation (G.D.P.R.) goes into effect on May 25 and is meant to ensure a common set of data rights in the European Union. It requires organizations to notify users as soon as possible of high-risk data breaches that could personally affect them.</P>
<P>With less than a month to go before the European Union enacts new consumer privacy laws for its citizens, companies around the world are updating their terms of service agreements to comply.</P>
<P>The European Union’s General Data Protection Regulation (G.D.P.R.) goes into effect on May 25 and is meant to ensure a common set of data rights in the European Union. It requires organizations to notify users as soon as possible of high-risk data breaches that could personally affect them.</P>
<P>With less than a month to go before the European Union enacts new consumer privacy laws for its citizens, companies around the world are updating their terms of service agreements to comply.</P>
<P>The European Union’s General Data Protection Regulation (G.D.P.R.) goes into effect on May 25 and is meant to ensure a common set of data rights in the European Union. It requires organizations to notify users as soon as possible of high-risk data breaches that could personally affect them.</P>
<P>With less than a month to go before the European Union enacts new consumer privacy laws for its citizens, companies around the world are updating their terms of service agreements to comply.</P>
<P>The European Union’s General Data Protection Regulation (G.D.P.R.) goes into effect on May 25 and is meant to ensure a common set of data rights in the European Union. It requires organizations to notify users as soon as possible of high-risk data breaches that could personally affect them.</P>
<P>With less than a month to go before the European Union enacts new consumer privacy laws for its citizens, companies around the world are updating their terms of service agreements to comply.</P>
<P>The European Union’s General Data Protection Regulation (G.D.P.R.) goes into effect on May 25 and is meant to ensure a common set of data rights in the European Union. It requires organizations to notify users as soon as possible of high-risk data breaches that could personally affect them.</P>
<P>With less than a month to go before the European Union enacts new consumer privacy laws for its citizens, companies around the world are updating their terms of service agreements to comply.</P>
<P>The European Union’s General Data Protection Regulation (G.D.P.R.) goes into effect on May 25 and is meant to ensure a common set of data rights in the European Union. It requires organizations to notify users as soon as possible of high-risk data breaches that could personally affect them.</P>
<P>With less than a month to go before the European Union enacts new consumer privacy laws for its citizens, companies around the world are updating their terms of service agreements to comply.</P>
<P>The European Union’s General Data Protection Regulation (G.D.P.R.) goes into effect on May 25 and is meant to ensure a common set of data rights in the European Union. It requires organizations to notify users as soon as possible of high-risk data breaches that could personally affect them.</P>
{#snippet footer()}
<Button type="submit">I accept</Button>
<Button type="submit" color="alternative">Decline</Button>
{/snippet}
</Modal>
Non-modal case
<script>
import { Button, Modal, P } from "flowbite-svelte";
let defaultModal = $state(false);
</script>
<Button onclick={() => (defaultModal = true)}>Default modal</Button>
<Modal title="Terms of Service" form bind:open={defaultModal} onaction={({ action }) => alert(`Handle "${action}"`)}>
<P>With less than a month to go before the European Union enacts new consumer privacy laws for its citizens, companies around the world are updating their terms of service agreements to comply.</P>
<P>The European Union’s General Data Protection Regulation (G.D.P.R.) goes into effect on May 25 and is meant to ensure a common set of data rights in the European Union. It requires organizations to notify users as soon as possible of high-risk data breaches that could personally affect them.</P>
{#snippet footer()}
<Button type="submit" value="success">I accept</Button>
<Button type="submit" value="decline" color="alternative">Decline</Button>
{/snippet}
</Modal>
No internal form
<script>
import { Button, Modal, Input, P } from "flowbite-svelte";
let open = $state(false);
</script>
<Button onclick={() => (open = true)}>No form modal</Button>
<Modal bind:open title="Custom form">
<form method="dialog" name="my_form" novalidate>
<fieldset class="flex gap-4 border p-4">
<legend class="px-2">Custom form</legend>
<Input required placeholder="This is separate form" />
<Button type="submit" value="accept" class="shrink-0">Submit button</Button>
</fieldset>
</form>
<P>With less than a month to go before the European Union enacts new consumer privacy laws for its citizens, companies around the world are updating their terms of service agreements to comply.</P>
{#snippet footer()}
<Button type="submit" value="accept">Submit button not in form</Button>
<Button onclick={() => (open = false)} color="alternative">Button with 'onclick' handler</Button>
{/snippet}
</Modal>
Modal events
<script lang="ts">
import { Button, Modal, P } from "flowbite-svelte";
let open = $state(false);
</script>
<Button onclick={() => (open = true)}>Default modal</Button>
<Modal form bind:open onsubmit={(ev) => alert(`SUBMIT: Form is about to be submitted.`)} oncancel={(ev) => alert("CANCEL: User canceled the dialog")} onclose={(ev) => alert(`CLOSE: Dialog closed with "${(ev.target as HTMLDialogElement)?.returnValue || "no"}" action.`)} title="Terms of Service">
<P>With less than a month to go before the European Union enacts new consumer privacy laws for its citizens, companies around the world are updating their terms of service agreements to comply.</P>
<P>The European Union's General Data Protection Regulation (G.D.P.R.) goes into effect on May 25 and is meant to ensure a common set of data rights in the European Union. It requires organizations to notify users as soon as possible of high-risk data breaches that could personally affect them.</P>
{#snippet footer()}
<Button type="submit" value="accept">I accept</Button>
<Button type="submit" value="decline" color="alternative">Decline</Button>
{/snippet}
</Modal>
Full-Screen Modal
<script>
import { Button, Modal, P } from 'svelte-5-ui-lib';
let defaultModal = $state(false);
</script>
<Button onclick={() => (defaultModal = true)}>Default modal</Button>
<Modal bind:open={defaultModal} fullscreen size="none" class="bg-gray-100">
<div class="flex h-screen items-center justify-center">
<P class="text-3xl">Content</P>
</div>
</Modal>