Check out BugBytes overview of labb

Modal

<c-lb.modal /> Markdown

Modal component for Django: create accessible dialogs and overlays without JavaScript. Built with django-cotton, Tailwind CSS, and daisyUI 5.

Modal uses CSS-driven dialog toggling via checkbox state, so no JavaScript is required. The c-lb.modal.action slot is the trigger; c-lb.modal.content holds the panel body. Closing works via the built-in close button or a backdrop click.

Basic Modal

<c-lb.button variant="primary" onclick="basic_modal.showModal()">Open Modal</c-lb.button>

<c-lb.modal id="basic_modal" boxClass="shadow border">
    <h3 class="text-lg font-bold">Hello!</h3>
    <p class="py-4">Press ESC key or click the button below to close</p>
    <c-lb.modal.action>
        <form method="dialog">
            <c-lb.button>Close</c-lb.button>
        </form>
    </c-lb.modal.action>
</c-lb.modal>

Default Slot Only

<!-- Open the modal using ID.showModal() method -->
<c-lb.button variant="primary" onclick="default_slot_modal.showModal()">Open Simple Modal</c-lb.button>

<c-lb.modal id="default_slot_modal" boxClass="shadow border">
  <h2 class="text-2xl font-bold mb-4">Default Slot Only</h2>
  <p class="mb-4">This modal only uses the default slot - content is automatically wrapped in modal.box.</p>
  <c-lb.modal.action>
    <form method="dialog">
      <c-lb.button>Close</c-lb.button>
    </form>
  </c-lb.modal.action>
</c-lb.modal>

Custom Box

<!-- Open the modal using ID.showModal() method -->
<c-lb.button variant="secondary" onclick="custom_box_modal.showModal()">Open Custom Box Modal</c-lb.button>

<c-lb.modal id="custom_box_modal" boxClass="shadow border">
  <c-slot name="box">
    <c-lb.modal.box size="lg" class="bg-gradient-to-br from-primary to-secondary text-primary-content" boxClass="shadow border">
      <h2 class="text-2xl font-bold mb-4">Custom Box Modal</h2>
      <p class="mb-4">This modal uses a custom box slot with a gradient background and larger size.</p>
      <c-lb.modal.action>
        <form method="dialog">
          <c-lb.button variant="accent">Close</c-lb.button>
        </form>
      </c-lb.modal.action>
    </c-lb.modal.box>
  </c-slot>
</c-lb.modal>

With Box Class

<div class="flex flex-wrap gap-4 items-center">
    <!-- Modal with custom box class -->
    <c-lb.button onclick="modal_with_box.showModal()">
        Open Modal with Custom Box
    </c-lb.button>
</div>

<c-lb.modal id="modal_with_box" boxClass="bg-gradient-to-br from-primary to-secondary text-primary-content shadow border">
    <p class="text-lg font-bold text-primary-content">Custom Styled Modal</p>
    <p class="py-4">This modal has a custom gradient background applied to its box using the `boxClass` prop.</p>
    <c-lb.modal.action>
        <form method="dialog">
            <c-lb.button>Close</c-lb.button>
        </form>
    </c-lb.modal.action>
</c-lb.modal>

Click Outside to Close

<c-lb.button variant="primary" onclick="backdrop_modal.showModal()">Open Modal</c-lb.button>

<c-lb.modal id="backdrop_modal" withBackdrop boxClass="shadow border">
    <h3 class="text-lg font-bold">Hello!</h3>
    <p class="py-4">Press ESC key or click outside to close</p>
</c-lb.modal>

Corner Close Button

<c-lb.button variant="primary" onclick="corner_close_modal.showModal()">Open Modal</c-lb.button>

<c-lb.modal id="corner_close_modal" withCloseBtn boxClass="shadow border">
    <h3 class="text-lg font-bold">Hello!</h3>
    <p class="py-4">Press ESC key or click on ✕ button to close</p>
</c-lb.modal>

Close Button Positions

<div class="flex gap-2 flex-wrap">
    <c-lb.button variant="outline" onclick="top_right_modal.showModal()">Top Right</c-lb.button>
    <c-lb.button variant="outline" onclick="top_left_modal.showModal()">Top Left</c-lb.button>
    <c-lb.button variant="outline" onclick="bottom_right_modal.showModal()">Bottom Right</c-lb.button>
    <c-lb.button variant="outline" onclick="bottom_left_modal.showModal()">Bottom Left</c-lb.button>
</div>

<c-lb.modal id="top_right_modal" withCloseBtn closeBtnPosition="top-right" boxClass="shadow border">
    <h3 class="font-bold text-lg">Top Right Close Button</h3>
    <p class="py-4">Close button is positioned at the top right corner</p>
    <c-lb.modal.action boxClass="shadow border">
        <form method="dialog">
            <c-lb.button>Close</c-lb.button>
        </form>
    </c-lb.modal.action>
</c-lb.modal>

<c-lb.modal id="top_left_modal" withCloseBtn closeBtnPosition="top-left" boxClass="shadow border">
    <div class="text-right">
        <h3 class="font-bold text-lg">Top Left Close Button</h3>
        <p class="py-4">Close button is positioned at the top left corner</p>
    </div>
    <c-lb.modal.action class="justify-start" boxClass="shadow border">
        <form method="dialog">
            <c-lb.button>Close</c-lb.button>
        </form>
    </c-lb.modal.action>
</c-lb.modal>

<c-lb.modal id="bottom_right_modal" withCloseBtn closeBtnPosition="bottom-right" boxClass="shadow border">
    <h3 class="font-bold text-lg">Bottom Right Close Button</h3>
    <p class="py-4">Close button is positioned at the bottom right corner</p>
    <c-lb.modal.action class="justify-start" boxClass="shadow border">
        <form method="dialog">
            <c-lb.button>Close</c-lb.button>
        </form>
    </c-lb.modal.action>
</c-lb.modal>

<c-lb.modal id="bottom_left_modal" withCloseBtn closeBtnPosition="bottom-left" boxClass="shadow border">
    <div class="text-right">
        <h3 class="font-bold text-lg">Bottom Left Close Button</h3>
        <p class="py-4">Close button is positioned at the bottom left corner</p>
    </div>
    <c-lb.modal.action class="justify-end" boxClass="shadow border">
        <form method="dialog">
            <c-lb.button>Close</c-lb.button>
        </form>
    </c-lb.modal.action>
</c-lb.modal>
<div class="flex gap-2 flex-wrap">
    <c-lb.button variant="outline" onclick="xs_modal.showModal()">XS Modal</c-lb.button>
    <c-lb.button variant="outline" onclick="sm_modal.showModal()">SM Modal</c-lb.button>
    <c-lb.button variant="outline" onclick="md_modal.showModal()">MD Modal</c-lb.button>
    <c-lb.button variant="outline" onclick="lg_modal.showModal()">LG Modal</c-lb.button>
    <c-lb.button variant="outline" onclick="xl_modal.showModal()">XL Modal</c-lb.button>
    <c-lb.button variant="outline" onclick="screen_modal.showModal()">Screen Modal</c-lb.button>
</div>

<c-lb.modal id="xs_modal" size="xs" boxClass="shadow border">
    <h3 class="font-bold text-lg">XS Modal</h3>
    <p class="py-4">This is an extra small modal</p>
    <c-lb.modal.action>
        <form method="dialog">
            <c-lb.button>Close</c-lb.button>
        </form>
    </c-lb.modal.action>
</c-lb.modal>

<c-lb.modal id="sm_modal" size="sm" boxClass="shadow border">
    <h3 class="font-bold text-lg">SM Modal</h3>
    <p class="py-4">This is a small modal</p>
    <c-lb.modal.action>
        <form method="dialog">
            <c-lb.button>Close</c-lb.button>
        </form>
    </c-lb.modal.action>
</c-lb.modal>

<c-lb.modal id="md_modal" size="md" boxClass="shadow border">
    <h3 class="font-bold text-lg">MD Modal</h3>
    <p class="py-4">This is a medium modal</p>
    <c-lb.modal.action>
        <form method="dialog">
            <c-lb.button>Close</c-lb.button>
        </form>
    </c-lb.modal.action>
</c-lb.modal>

<c-lb.modal id="lg_modal" size="lg" boxClass="shadow border">
    <h3 class="font-bold text-lg">LG Modal</h3>
    <p class="py-4">This is a large modal</p>
    <c-lb.modal.action>
        <form method="dialog">
            <c-lb.button>Close</c-lb.button>
        </form>
    </c-lb.modal.action>
</c-lb.modal>

<c-lb.modal id="xl_modal" size="xl" boxClass="shadow border">
    <h3 class="font-bold text-lg">XL Modal</h3>
    <p class="py-4">This is an extra large modal</p>
    <c-lb.modal.action>
        <form method="dialog">
            <c-lb.button>Close</c-lb.button>
        </form>
    </c-lb.modal.action>
</c-lb.modal>

<c-lb.modal id="screen_modal" size="screen" boxClass="shadow border">
    <h3 class="font-bold text-lg">Screen Modal</h3>
    <p class="py-4">This modal takes up most of the screen width</p>
    <c-lb.modal.action>
        <form method="dialog">
            <c-lb.button>Close</c-lb.button>
        </form>
    </c-lb.modal.action>
</c-lb.modal>
<div class="flex gap-2 flex-wrap">
    <c-lb.button variant="outline" onclick="top_modal.showModal()">Top Modal</c-lb.button>
    <c-lb.button variant="outline" onclick="middle_modal.showModal()">Middle Modal</c-lb.button>
    <c-lb.button variant="outline" onclick="bottom_modal.showModal()">Bottom Modal</c-lb.button>
    <c-lb.button variant="outline" onclick="start_modal.showModal()">Start Modal</c-lb.button>
    <c-lb.button variant="outline" onclick="end_modal.showModal()">End Modal</c-lb.button>
</div>

<c-lb.modal id="top_modal" placement="top" withBackdrop boxClass="shadow border">
    <h3 class="font-bold text-lg">Top Placement</h3>
    <p class="py-4">This modal appears at the top of the screen</p>
    <c-lb.modal.action boxClass="shadow border">
        <form method="dialog">
            <c-lb.button>Close</c-lb.button>
        </form>
    </c-lb.modal.action>
</c-lb.modal>

<c-lb.modal id="middle_modal" placement="middle" withBackdrop boxClass="shadow border">
    <h3 class="font-bold text-lg">Middle Placement</h3>
    <p class="py-4">This modal appears in the middle of the screen (default)</p>
    <c-lb.modal.action boxClass="shadow border">
        <form method="dialog">
            <c-lb.button>Close</c-lb.button>
        </form>
    </c-lb.modal.action>
</c-lb.modal>

<c-lb.modal id="bottom_modal" placement="bottom" withBackdrop boxClass="shadow border">
    <h3 class="font-bold text-lg">Bottom Placement</h3>
    <p class="py-4">This modal appears at the bottom of the screen</p>
    <c-lb.modal.action boxClass="shadow border">
        <form method="dialog">
            <c-lb.button>Close</c-lb.button>
        </form>
    </c-lb.modal.action>
</c-lb.modal>

<c-lb.modal id="start_modal" placement="start" withBackdrop boxClass="shadow border">
    <h3 class="font-bold text-lg">Start Alignment</h3>
    <p class="py-4">This modal appears at the start (left) of the screen</p>
    <c-lb.modal.action boxClass="shadow border">
        <form method="dialog">
            <c-lb.button>Close</c-lb.button>
        </form>
    </c-lb.modal.action>
</c-lb.modal>

<c-lb.modal id="end_modal" placement="end" withBackdrop boxClass="shadow border">
    <h3 class="font-bold text-lg">End Alignment</h3>
    <p class="py-4">This modal appears at the end (right) of the screen</p>
    <c-lb.modal.action boxClass="shadow border">
        <form method="dialog">
            <c-lb.button>Close</c-lb.button>
        </form>
    </c-lb.modal.action>
</c-lb.modal>

Responsive Modal

<c-lb.button variant="primary" onclick="responsive_modal.showModal()">Open Responsive Modal</c-lb.button>

<c-lb.modal id="responsive_modal" placement="bottom" class="sm:modal-middle" boxClass="shadow border">
    <h3 class="text-lg font-bold">Responsive Modal</h3>
    <p class="py-4">This modal goes bottom on small screens, middle on medium screens and up</p>
    <c-lb.modal.action>
        <form method="dialog">
            <c-lb.button>Close</c-lb.button>
        </form>
    </c-lb.modal.action>
</c-lb.modal>

Confirmation Dialog

<c-lb.button variant="error" onclick="confirm_modal.showModal()">Delete Item</c-lb.button>

<c-lb.modal id="confirm_modal" withBackdrop boxClass="shadow border">
    <div class="flex items-center gap-4">
        <div class="flex-shrink-0">
            <svg xmlns="http://www.w3.org/2000/svg" class="h-12 w-12 text-error" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
            </svg>
        </div>
        <div>
            <h3 class="font-bold text-lg">Delete Confirmation</h3>
            <p class="py-2">Are you sure you want to delete this item? This action cannot be undone.</p>
        </div>
    </div>

    <c-lb.modal.action class="justify-end">
        <form method="dialog" class="flex gap-2">
            <c-lb.button>Cancel</c-lb.button>
            <c-lb.button variant="error">Delete</c-lb.button>
        </form>
    </c-lb.modal.action>
</c-lb.modal>

Notification Modal

<c-lb.button variant="info" onclick="notification_modal.showModal()">Show Notification</c-lb.button>

<c-lb.modal id="notification_modal" withCloseBtn withBackdrop boxClass="shadow border">
    <div class="text-center">
        <div class="flex justify-center mb-4">
            <svg xmlns="http://www.w3.org/2000/svg" class="h-16 w-16 text-success" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
            </svg>
        </div>
        <h3 class="font-bold text-xl mb-2">Success!</h3>
        <p class="py-4 text-base-content/70">Your action has been completed successfully.</p>
    </div>

    <c-lb.modal.action class="justify-center">
        <form method="dialog">
            <c-lb.button variant="success">Got it</c-lb.button>
        </form>
    </c-lb.modal.action>
</c-lb.modal>

Combined Features

<c-lb.button variant="primary" onclick="combined_modal.showModal()">Open Combined Features Modal</c-lb.button>

<c-lb.modal
    id="combined_modal"
    placement="top"
    withBackdrop
    withCloseBtn
    closeBtnPosition="top-left"
    boxClass="shadow border"
>
    <div class="text-right">
        <h3 class="font-bold text-lg">Combined Features Modal</h3>
        <p class="py-4">This modal demonstrates multiple features combined:</p>
        <ul class="list-disc list-inside space-y-2">
            <li>Top placement</li>
            <li>Backdrop overlay</li>
            <li>Close button at top-left</li>
            <li>Default slot content</li>
        </ul>
    </div>
    <c-lb.modal.action class="justify-start">
        <form method="dialog">
            <c-lb.button>Close</c-lb.button>
        </form>
    </c-lb.modal.action>
</c-lb.modal>

API Reference

c-lb.modal

Property Type Default Required Description
class string - No Additional CSS classes to apply
id string - Yes Unique ID for the modal dialog (required for showModal/close methods)
placement
top middle bottom start end
middle No Modal position on screen
open boolean False No Whether modal is initially open
size
map modal.box:size
- No Modal box size (for default box)
boxClass string - No Additional CSS classes to apply to the default modal box
withBackdrop
map modal.backdrop
- No Add a backdrop overlay for closing when clicked outside
withCloseBtn
map modal.close
- No Add a close button to the modal
closeBtnPosition
map modal.close:position
- No Position of the close button
Slot Name Description
default Modal content (automatically wrapped in modal.box)
box Custom modal box content (overrides default slot)

c-lb.modal.box

Property Type Default Required Description
class string - No Additional CSS classes to apply
size
xs sm md lg xl screen
- No Modal box size

c-lb.modal.action

Property Type Default Required Description
class string - No Additional CSS classes to apply

c-lb.modal.backdrop

Property Type Default Required Description
class string - No Additional CSS classes to apply

c-lb.modal.close

Property Type Default Required Description
class string - No Additional CSS classes to apply
variant
neutral primary secondary accent info success warning error
- No Button color variant
position
top-right top-left bottom-right bottom-left
top-right No Position of the close button