DEV Community

artydev
artydev

Posted on

FastHTML : dealing with Modals with the help of Hyperscript

Here is a nice way to open a modal in FastHTML and Hyperscript
There is absolutely no Javascript

from fasthtml.common import *

app, rt = fast_app(
    hdrs=(
        StyleX("./static/styledev.css"),
        Script(src="https://unpkg.com/hyperscript.org@0.9.12"),
    ),
    live=True,
)


@app.get("/modal")
def modal():
    return Div(
        Div(_="on click trigger closeModal", cls="modal-underlay"),
        Div(
            H1("Modal Dialog"),
            P("This is the modal content"),
            P("You can put anything here, like text, or a form, or an image."),
            Button("Close", _="on click trigger closeModal", cls="btn danger"),
            cls="modal-content",
        ),
        id="modal",
        _="on closeModal add .closing then wait for animationend then remove me",
    )


@app.get("/")
def home():
    return Div(
        H2("Modal with FastHTML and Hyperscript", style="text-align:center"),
        Button(
            "Open a Modal",
            hx_get="/modal",
            hx_target="body",
            hx_swap="beforeend",
            cls="btn primary",
        ),
    )

serve(port=3333) 

Enter fullscreen mode Exit fullscreen mode

The CSS part :

/***** MODAL DIALOG ****/
#modal {
    /* Underlay covers entire screen. */
    position: fixed;
    top:0px;
    bottom: 0px;
    left:0px;
    right:0px;
    background-color:rgba(0,0,0,0.5);
    z-index:1000;

    /* Flexbox centers the .modal-content vertically and horizontally */
    display:flex;
    flex-direction:column;
    align-items:center;

    /* Animate when opening */
    animation-name: fadeIn;
    animation-duration:150ms;
    animation-timing-function: ease;
}

#modal > .modal-underlay {
    /* underlay takes up the entire viewport. This is only
    required if you want to click to dismiss the popup */
    position: absolute;
    z-index: -1;
    top:0px;
    bottom:0px;
    left: 0px;
    right: 0px;
}

#modal > .modal-content {
    /* Position visible dialog near the top of the window */
    margin-top:10vh;

    /* Sizing for visible dialog */
    width:80%;
    max-width:600px;

    /* Display properties for visible dialog*/
    border:solid 1px #999;
    border-radius:8px;
    box-shadow: 0px 0px 20px 0px rgba(0,0,0,0.3);
    background-color:white;
    padding:20px;

    /* Animate when opening */
    animation-name:zoomIn;
    animation-duration:150ms;
    animation-timing-function: ease;
}

#modal.closing {
    /* Animate when closing */
    animation-name: fadeOut;
    animation-duration:150ms;
    animation-timing-function: ease;
}

#modal.closing > .modal-content {
    /* Animate when closing */
    animation-name: zoomOut;
    animation-duration:150ms;
    animation-timing-function: ease;
}

@keyframes fadeIn {
    0% {opacity: 0;}
    100% {opacity: 1;}
}

@keyframes fadeOut {
    0% {opacity: 1;}
    100% {opacity: 0;}
}

@keyframes zoomIn {
    0% {transform: scale(0.9);}
    100% {transform: scale(1);}
}

@keyframes zoomOut {
    0% {transform: scale(1);}
    100% {transform: scale(0.9);}
}

Enter fullscreen mode Exit fullscreen mode

Heroku

This site is built on Heroku

Join the ranks of developers at Salesforce, Airbase, DEV, and more who deploy their mission critical applications on Heroku. Sign up today and launch your first app!

Get Started

Top comments (0)

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more