The ModalDialog function creates a modal dialog component using DaisyUI’s modal system.
Key features: - Native HTML <dialog> element with DaisyUI styling - Customizable sizes (small, medium, large, xlarge, full, or custom) - Optional close button (top-right X button) - Optional backdrop for closing on outside click - Support for HTMX updates to modal content - Programmatic show/close via JavaScript API - Auto-show support for immediate display - Flexible content area with optional styling
def ModalDialog( modal_id:str, # Unique identifier for the modal content:Any, # Content to display in the modal size:Union=<ModalSize.MEDIUM: 'md'>, # Size preset or custom size show_close_button:bool=True, # Whether to show X close button in top-right close_on_backdrop:bool=True, # Whether clicking backdrop closes modal auto_show:bool=False, # Whether to show modal immediately on render content_id:Optional=None, # Optional ID for content area (for HTMX targeting) custom_width:Optional=None, # Custom width class (e.g., "w-96") custom_height:Optional=None, # Custom height class (e.g., "h-screen") box_cls:Optional=None, # Additional classes for modal box kwargs:VAR_KEYWORD)->FT: # Dialog element with modal dialog configured
Create a modal dialog using native HTML dialog element with DaisyUI styling.
Trigger Button Helper
Helper function to create a button that opens a modal dialog.
def ModalTriggerButton( modal_id:str, # ID of the modal to trigger label:str, # Button label text button_cls:Optional=None, # Additional button classes kwargs:VAR_KEYWORD)->FT: # Button element that triggers modal
Create a button that opens a modal dialog.
Usage Examples
Here are complete examples showing different modal use cases:
from cjm_fasthtml_daisyui.components.data_display.card import card_body, card_titlefrom cjm_fasthtml_daisyui.components.actions.button import btn_colors# Example 1: Simple info modalsimple_modal = ModalDialog( modal_id="info", content=Div( H2("Information", cls=str(card_title)), P("This is a simple informational modal."), cls=str(card_body) ), size=ModalSize.SMALL)# Trigger buttontrigger_btn = ModalTriggerButton( modal_id="info", label="Show Info", button_cls=str(btn_colors.info))print("Example 1: Simple info modal")print(f"Modal ID: {InteractionHtmlIds.modal_dialog('info')}")print(f"Trigger: {trigger_btn}")
Example 1: Simple info modal
Modal ID: modal-info
Trigger: <button onclick="document.getElementById('modal-info').showModal()" class="btn btn-info">Show Info</button>
# Example 2: Large modal with HTMX content loadingfrom cjm_fasthtml_interactions.patterns.async_loading import AsyncLoadingContainer, LoadingType# Modal with async loading contentloading_modal = ModalDialog( modal_id="settings", content=AsyncLoadingContainer( container_id="settings-form", load_url="/api/settings/form", loading_type=LoadingType.SPINNER, loading_message="Loading settings..." ), size=ModalSize.LARGE, content_id="settings-form")print("Example 2: Modal with async content")print(f"Modal ID: {InteractionHtmlIds.modal_dialog('settings')}")print(f"Content ID: {InteractionHtmlIds.modal_dialog_content('settings')}")
Example 2: Modal with async content
Modal ID: modal-settings
Content ID: modal-settings-content
# Example 3: Full-screen modal for media viewingfullscreen_modal = ModalDialog( modal_id="media-viewer", content=Div( Img(src="/images/large-photo.jpg", alt="Photo"), cls=combine_classes("flex", "items-center", "justify-center") ), size=ModalSize.FULL, show_close_button=True, close_on_backdrop=True)print("Example 3: Full-screen media viewer")print(f"Modal ID: {InteractionHtmlIds.modal_dialog('media-viewer')}")
Example 3: Full-screen media viewer
Modal ID: modal-media-viewer
# Example 4: Custom size modal with auto-showcustom_modal = ModalDialog( modal_id="welcome", content=Div( H2("Welcome!", cls=str(card_title)), P("Thanks for visiting our app."), cls=str(card_body) ), size=ModalSize.CUSTOM, custom_width="w-96", custom_height="h-48", auto_show=True)print("Example 4: Custom size with auto-show")print(f"Modal ID: {InteractionHtmlIds.modal_dialog('welcome')}")
Example 4: Custom size with auto-show
Modal ID: modal-welcome
Programmatic Control
You can show and close modals programmatically using JavaScript:
// Show modaldocument.getElementById('modal-my-modal').showModal();// Close modaldocument.getElementById('modal-my-modal').close();
Or in Python, using the helper to generate the correct JavaScript:
# In your button onclickButton("Open Modal", onclick=f"document.getElementById('{InteractionHtmlIds.modal_dialog('my-modal')}').showModal()")# Or use ModalTriggerButton helperModalTriggerButton( modal_id="my-modal", label="Open Modal")
HTMX Integration
Modals work seamlessly with HTMX for dynamic content updates:
Update Modal Content
Target the content area to update modal contents:
# Create modal with content IDmodal = ModalDialog( modal_id="details", content=Div("Initial content", id="details-content"), content_id="details-content")# Button that updates modal content and shows itButton("Load Details", hx_get="/api/details/123", hx_target=InteractionHtmlIds.as_selector( InteractionHtmlIds.modal_dialog_content("details") ), hx_swap="innerHTML",# Show modal after content loads hx_on__after_swap=f"document.getElementById('{InteractionHtmlIds.modal_dialog('details')}').showModal()")
Close Modal After Action
Close modal after a successful form submission:
# Form inside modalForm(# ... form fields ... Button("Save", type="submit"), hx_post="/api/save",# Close modal on success hx_on__after_request=f""" if (event.detail.successful) {{ document.getElementById('{InteractionHtmlIds.modal_dialog('my-modal')}').close();}} """)
Server-Side Responses
When updating modal content via HTMX, return just the content:
@app.get("/api/details/{id}")def get_details(id: str):# Load data details = load_details(id)# Return just the content (will replace content area)return Div( H2(details["title"]), P(details["description"]),# Include ID to match targetid=InteractionHtmlIds.modal_dialog_content("details") )
To show a modal from server-side response, use OOB swap:
@app.post("/api/trigger-action")def trigger_action():# Perform action result = do_something()# Create modal with auto-show result_modal = ModalDialog( modal_id="result", content=Div( H2("Success!"), P(f"Action completed: {result}") ), auto_show=True )# Add OOB swap to inject modal into page result_modal.attrs['hx-swap-oob'] ='beforeend:body'return Div( P("Action completed"), # Main response result_modal # OOB modal )