Modal

The <Modal> component is used to display an interactive modal dialog.

Properties

Name
Default
Description
show
false
If true, the modal will be displayed.
title
The title of the modal.
size
medium
The size of the modal.
  • small
  • medium
  • large
id
modal
An id to be used in the aria-labelledby and aria-describedby attributes. Only required if you are using multiple modals at the same time.
role
alertdialog
alertdialog or dialog. Use the latter if the modal is not an alert.
closeOnOutsideClick
true
Whether to close the modal when clicking outside of it.
closeOnEscape
true
Whether to close the modal when pressing the escape key.
loading
false
Whether to show a loader. See Loading State.
footer
null
To display a common footer with a cancel and a confirm button. See Modal Footer.

Slots

Name
Description
default
The content/body of the modal.
title
Override the title property of the modal.
footer
The footer of the modal.

Examples

Basic Modal

<script>
    import { Modal, Button } from '@hyvor/design/components';
    let show = false;
</script>

<Button on:click={() => show = true}>Show modal</Button>

<Modal title="Confirm to delete" bind:show={show}>

    Please confirm that you want to delete this item. This action cannot be undone.

    <div slot="footer">
        <Button variant="invisible" on:click={() => show = false}>Cancel</Button>
        <Button color="red">Delete</Button>
    </div>

</Modal>

Sizes

Set the size attribute to small, medium or large to change the size of the modal.

Title Slot

You can use the title slot to customize the title of the modal.

<Modal bind:show={show} size="large">

    <TabNav active="paste" slot="title">
        <TabNavItem name="paste">
            <IconLink45deg slot="start" />
            Paste Link
        </TabNavItem>
        <TabNavItem name="posts">
            <IconSearch slot="start" />
            Search Posts
        </TabNavItem>
    </TabNav>

    This is a modal with a tab navigation in the title.

    <div slot="footer">
        <Button variant="invisible" on:click={() => show5 = false}>Close</Button>
    </div>

</Modal>

Scrollable Modal

If a modal grows larger than the screen, it will be scrollable. The inner content will be aligned to the top of the modal.

Loading state

You can use the loading property to display a loading spinner in the modal. It accepts a string or a boolean. If a string is passed, it will be displayed as the loading text. This is the recommended way to display a loading state in a modal, due to the following issues with other methods:

Loading Method
Issue
Loading toast
The user can still interact with the modal.
Closing the modal and showing a toast
The user's input will be lost in case of an error.
Show a loader in the button manually
The user can still interact with the modal. Also, more code is required.
Using the loading property
None

Setting the loading property will disable the close button, escape key, and the outside click to close the modal. Therefore, you should handle both success and error cases manually.

Instead of manually setting the footer slot, you can set the footer property of the modal to display a common footer with a cancel and a confirm button.

<Modal
    ...
    footer={{
        cancel: {
            text: 'Cancel',
        },
        confirm: {
            text: 'Delete',
            danger: true
        }
    }}
    on:cancel={() => toast.success('Cancelled')}
    on:confirm={() => {
        show = false;
        toast.success('Deleted')
    }}
/>

The footer property accepts an object with the following properties:

interface Footer {
    // cancel button
    // set to false to hide the button
    cancel?: {
        // text of the button (default: "Cancel")
        text?: string,
        // props to pass to the button
        props?: Record<string, any>
    },
    // confirm button
    confirm?: {
        // text of the button (default: "Confirm")
        text?: string,
        // props to pass to the button
        props?: Record<string, any>,
        // whether the button is a danger button (button color will be red)
        danger?: boolean
    }
}

Confirm

Confirm modals are used frequently in web applications to confirm an action. You can use the confirm function to display a confirm modal.

import { confirm } from '@hyvor/design/components';

async function handleDelete() {
    const confirmed = await confirm({
        title: 'Confirm to delete',
        content: 'Please confirm that you want to delete this item. This action cannot be undone.',
        danger: true
    });

    if (confirmed) {
        // Delete the item
    }
}

The confirm function accepts an object with the following properties:

interface ConfirmOptions {
    // title of the modal
    title: string,

    // content of the modal. Can be a string or a Svelte component
    content: string | SvelteComponent,

    // props to pass to the content component
    contentProps?: Record<string, any>,
    
    // text of the confirm button (default: "Confirm")
    confirmText?: string,
    
    // text of the cancel button (default: "Cancel")
    cancelText?: string,
    
    // whether the modal is a danger modal (button color will be red)
    danger?: boolean,

    // whether the modal is loading - see Confirm with Loader
    loading?: boolean;

    // whether to close the modal when the confirm button is clicked
    // default: true
    autoClose?: boolean;
}

Confirm with Loader

First, set the autoClose property to false to prevent the modal from closing when the confirm button is clicked. Then, use the loading method of the returned object to set the modal loading state. Finally, close the modal manually using the close method.

import { confirm } from '@hyvor/design/components';

async function handleDelete() {
    const confirmed = await confirm({
        title: 'Update your username',
        content: 'Are you sure you want to update your username to "newusername"?',
        confirmText: "Update",
        autoClose: false,
    });

    if (confirmed) {
        confirmed.loading('Updating your username...');
        await updateUsername('newusername');
        confirmed.close();
    }
}