Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compatible with HTMX? #697

Open
anentropic opened this issue Jun 5, 2024 · 1 comment
Open

Compatible with HTMX? #697

anentropic opened this issue Jun 5, 2024 · 1 comment

Comments

@anentropic
Copy link

anentropic commented Jun 5, 2024

I'm trying to evaluate whether this library will work with HTMX.

So i.e. with one of the non-SPA framework integration options, such as https://www.material-tailwind.com/docs/html/guide/django

The docs show that in this case you should add the script tag at the bottom of the page.

Looking at the contents of the script (e.g. for Ripple effect) it seems that this is a run-once initialisation, via a self-invoking anonymous function.

I haven't tried it, but seems like this is not going to work with HTMX since any components loaded by subsequent request won't be initialised, and there's no way to get a reference to the initialiser to call it manually.

OTOH the React integration docs recommend exactly the same thing: https://www.material-tailwind.com/docs/html/guide/react-vite#ripple-effect so perhaps I am missing something about how this works?

Or maybe those docs are obsolete? I see elsewhere there are different docs https://www.material-tailwind.com/docs/react/guide/vite which show installing dedicated React components npm i @material-tailwind/react and not adding the script tag, seems like that way is more likely to work for an SPA.

My questions are:

  • Have I understood correctly about HTMX with default non-SPA integration style?
  • Is there an alternative that will work?
@TimCanu
Copy link

TimCanu commented Sep 14, 2024

Hello.
Here is an alternative that will work:

Create a script ripple.js:

function createRipple(event) {
    const element = event.currentTarget;
    element.classList.add("relative")
    element.classList.add("overflow-hidden")

    const circle = document.createElement("span");
    const diameter = Math.max(element.clientWidth, element.clientHeight);
    const radius = diameter / 2;

    circle.style.width = circle.style.height = `${diameter}px`;
    circle.style.left = `${event.clientX - element.offsetLeft - radius}px`;
    circle.style.top = `${event.clientY - element.offsetTop - radius}px`;
    circle.classList.add("ripple");

    const ripple = element.getElementsByClassName("ripple")[0];

    if (ripple) {
        ripple.remove();
    }

    element.appendChild(circle);
}

function removeRipple(element) {
    const ripple = element.getElementsByClassName("ripple")[0];

    if (ripple) {
        console.log('removing')
        ripple.remove();
    }
}

function initRippleElements(target) {
    const elements = target.querySelectorAll('[data-ripple-light="true"]');
    for (const element of elements) {
        // This is to support the back button
        removeRipple(element)
        element.addEventListener("click", createRipple);
    }
}

initRippleElements(document)
addEventListener("htmx:afterSwap", e => initRippleElements(e.target));

In your tailwind input file add this:

span.ripple {
    position: absolute;
    border-radius: 50%;
    transform: scale(0);
    animation: ripple 600ms linear;
    background-color: rgba(255, 255, 255, 0.7);
}

@keyframes ripple {
    to {
        transform: scale(4);
        opacity: 0;
    }
}

In you html <head> tag add the script:

<script src="/assets/scripts/ripple.js"></script>

This will work on element such as this one:

<a
    href="/foo/bar"
    class="flex flex-col border border-green-400 rounded-md shadow-sm shadow-black hover:shadow-black hover:border-black hover:shadow-md"
    hx-boost="true"
    data-ripple-light="true"
>

It obviously works on button too (it works on all elements).

This solution in inspired from this: https://css-tricks.com/how-to-recreate-the-ripple-effect-of-material-design-buttons/
I can explain more if required. There might be a few issues that I did not consider and some improvements that can be made. 🙂

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants