Qwik modal - Flowbite

Use the modal component to show an interactive dialog to your website users that overlays the main content based on multiple sizes, layouts, and styles

The modal component can be used to show any type of content such as text, form elements, and notifications to your website visitors by creating an off-canvas box on top of the main content area of your website.

You can choose from multiple examples based on various styles, layouts, and elements inside the modal component and you can customize the behaviour, placement, and sizing using our custom Qwik props and the utility classes from Tailwind CSS.

To get started with the modal component you first need to import it from flowbite-qwik :

import { Modal } from "flowbite-qwik"

Default modal

Use the <Modal> component to show a dialog element to the user with a header, body, and footer where you can add any type of content such as text or form elements. The visibility of the component can be set by passing a boolean value to the bind:show prop on the <Modal> component.

tsx
import { component$, useSignal } from '@builder.io/qwik'
import { Button, Modal } from 'flowbite-qwik'

export default component$(() => {
  const defaultModalVisible = useSignal(false)

  return (
    <div>
      <Button
        onClick$={() => {
          defaultModalVisible.value = true
        }}
      >
        Open Modal
      </Button>
      <Modal
        header={<div class="flex items-center text-lg">Terms of Service</div>}
        footer={
          <div class="flex justify-between">
            <Button
              onClick$={() => {
                defaultModalVisible.value = false
              }}
              color="alternative"
            >
              Decline
            </Button>
            <Button
              onClick$={() => {
                defaultModalVisible.value = false
              }}
              color="green"
            >
              I accept
            </Button>
          </div>
        }
        bind:show={defaultModalVisible}
        onClickOutside$={() => {
          console.log('click outside !')
        }}
      >
        <p class="text-base leading-relaxed text-gray-500 dark:text-gray-400">
          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 class="text-base leading-relaxed text-gray-500 dark:text-gray-400">
          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>
      </Modal>
    </div>
  )
})

You can use four different modal sizing options starting from small to extra large, but keep in mind that the width of these modals will remain the same when browsing on smaller devices.

tsx
import { component$, Signal, useSignal, useStore } from '@builder.io/qwik'
import { Button, Modal, ModalSize } from 'flowbite-qwik'

export default component$(() => {
  const sizeModalVisible = useStore<Record<string, Signal<boolean>>>({
    xs: useSignal(false),
    md: useSignal(false),
    xl: useSignal(false),
    ['5xl']: useSignal(false),
  })

  return (
    <ul class="flex gap-2">
      {['xs', 'md', 'xl', '5xl'].map((size) => (
        <li key={size}>
          <Button
            onClick$={() => {
              sizeModalVisible[size].value = true
            }}
          >
            {size.toUpperCase()} Modal
          </Button>
          <Modal size={size as ModalSize} header={<div class="flex items-center text-lg">Size {size}</div>} bind:show={sizeModalVisible[size]}>
            <p class="text-base leading-relaxed text-gray-500 dark:text-gray-400">
              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>
            {size !== 'xs' && (
              <p class="text-base leading-relaxed text-gray-500 dark:text-gray-400">
                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>
            )}
          </Modal>
        </li>
      ))}
    </ul>
  )
})

The escapable property is true by default to improve user experience and accessibility. In some situations, your user may be required to interact with the modal content. If this is the case, you can set the notEscapable property to true. The developer can then choose when they want to close the modal.

tsx
import { component$, useSignal } from '@builder.io/qwik'
import { Button, Modal } from 'flowbite-qwik'

export default component$(() => {
  const escapeModalVisible = useSignal(false)

  return (
    <div>
      <Button
        onClick$={() => {
          escapeModalVisible.value = true
        }}
      >
        Open Not Escapable Modal
      </Button>
      <Modal
        notEscapable
        header={<div class="flex items-center text-lg">Terms of Service</div>}
        footer={
          <div class="flex justify-between">
            <Button
              onClick$={() => {
                escapeModalVisible.value = false
              }}
              color="alternative"
            >
              Decline
            </Button>
          </div>
        }
        bind:show={escapeModalVisible}
      >
        <p class="text-base leading-relaxed text-gray-500 dark:text-gray-400">
          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 class="text-base leading-relaxed text-gray-500 dark:text-gray-400">
          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>
      </Modal>
    </div>
  )
})

Clicking outside the element or pressing esc key will not send close event.

tsx
import { component$, useSignal } from '@builder.io/qwik'
import { Button, Modal } from 'flowbite-qwik'

export default component$(() => {
  const persistentModalVisible = useSignal(false)

  return (
    <div>
      <Button
        onClick$={() => {
          persistentModalVisible.value = true
        }}
      >
        Open Persistent Modal
      </Button>
      <Modal
        notEscapable
        persistent
        header={<div class="flex items-center text-lg">Terms of Service</div>}
        footer={
          <div class="flex justify-between">
            <Button
              onClick$={() => {
                persistentModalVisible.value = false
              }}
              color="alternative"
            >
              Decline
            </Button>
          </div>
        }
        bind:show={persistentModalVisible}
      >
        <p class="text-base leading-relaxed text-gray-500 dark:text-gray-400">
          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 class="text-base leading-relaxed text-gray-500 dark:text-gray-400">
          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>
      </Modal>
    </div>
  )
})

Pop-up modal

You can use this modal example to show a pop-up decision dialog to your users especially when deleting an item and making sure if the user really wants to do that by double confirming.

tsx
import { component$, useSignal } from '@builder.io/qwik'
import { Button, Modal } from 'flowbite-qwik'
import { IconBullhornSolid } from 'flowbite-qwik-icons'

export default component$(() => {
  const popupModalVisible = useSignal(false)

  return (
    <div>
      <Button
        onClick$={() => {
          popupModalVisible.value = true
        }}
      >
        Open Modal
      </Button>
      <Modal bind:show={popupModalVisible} size="md" popup>
        <div class="text-center">
          <IconBullhornSolid 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="flex justify-center gap-2">
            <Button color="red">Yes, I'm sure</Button>
            <Button outline>No, cancel</Button>
          </div>
        </div>
      </Modal>
    </div>
  )
})