Biblioteca de Componentes

Explora y reutiliza componentes creados por el equipo

Cookies PopUp

Popups

PopUp de cookies

Preview:

        <div id="popup-root">
  <div
    id="popup"
    class="fixed right-5 bottom-5 z-50 hidden w-[350px] items-center justify-center rounded-2xl bg-linear-to-tr from-zinc-700 via-zinc-800 to-zinc-900 p-2"
  >
    <button
      id="close-btn"
      class="absolute -top-2 -right-2 flex h-10 w-10 cursor-pointer items-center justify-center rounded-full border border-zinc-200 bg-zinc-100 shadow-lg transition-colors hover:bg-gray-100"
    >
      <svg
        xmlns="http://www.w3.org/2000/svg"
        class="h-6 w-6"
        fill="none"
        viewBox="0 0 24 24"
        stroke="currentColor"
        stroke-width="2"
      >
        <line x1="18" y1="6" x2="6" y2="18"></line>
        <line x1="6" y1="6" x2="18" y2="18"></line>
      </svg>
    </button>
    <div class="w-full space-y-3 rounded-xl bg-white p-6">
      <h3 class="text-2xl font-bold">🍪 Política de Cookies</h3>
      <p class="text-sm text-neutral-600">
        Utilizamos cookies para mejorar tu experiencia en nuestro sitio web.
        Estas nos ayudan a entender cómo usas nuestro sitio y a personalizar el
        contenido.
      </p>
      <div class="space-y-2 text-xs text-neutral-500">
        <p>
          <strong>Cookies esenciales:</strong> Necesarias para el funcionamiento básico
          del sitio.
        </p>
        <p>
          <strong>Cookies analíticas:</strong> Nos ayudan a mejorar el rendimiento
          del sitio.
        </p>
        <p>
          <strong>Cookies de marketing:</strong> Permiten personalizar anuncios y
          contenido.
        </p>
      </div>
      <button
        id="action-btn"
        class="min-h-[40px] w-full cursor-pointer rounded-md bg-blue-500 font-medium text-white transition-colors hover:bg-blue-600"
      >
        Aceptar todas las cookies
      </button>
    </div>
  </div>
</div>

<script type="module">
  import { animate } from "https://cdn.jsdelivr.net/npm/motion@11.11.13/+esm";

  const popup = document.getElementById("popup");
  const closeBtn = document.getElementById("close-btn");
  const actionBtn = document.getElementById("action-btn");

  let showPopUp = false;

  setTimeout(() => {
    showPopUp = true;
    popup.classList.remove("hidden");
    animate(
      popup,
      { opacity: [0, 1], y: [20, 0] },
      { duration: 0.3, ease: "easeOut" },
    );
  }, 1000);

  closeBtn.addEventListener("click", () => {
    popup.classList.add("hidden");
    showPopUp = false;
    // Rechazar cookies y no cargar GTM
    if (typeof window.cookieConsentReject === 'function') {
      window.cookieConsentReject();
    }
  });

  actionBtn.addEventListener("click", () => {
    popup.classList.add("hidden");
    showPopUp = false;
    // Aceptar cookies y cargar GTM
    if (typeof window.cookieConsentAccept === 'function') {
      window.cookieConsentAccept();
    }
  });
</script>
      

Button Primary

Buttons

Botón principal con estilo moderno y hover effects

Preview:

        <button class="px-6 py-3 bg-neutral-900 text-white rounded-lg font-medium cursor-pointer hover:bg-neutral-800">
  Click me
</button>
      

Card Simple

Cards

Tarjeta básica con borde y padding

Preview:

Card Title

Card content goes here

        <div class="p-6 bg-white border border-neutral-200 rounded-lg">
  <h3 class="text-lg font-semibold mb-2">Card Title</h3>
  <p class="text-neutral-500">Card content goes here</p>
</div>
      

Input Text

Forms

Campo de texto con estilo consistente

Preview:

        <input 
  type="text" 
  placeholder="Enter text..." 
  class="w-full px-4 py-2.5 border border-neutral-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-neutral-400"
/>
      

Badge

UI Elements

Badge para etiquetas y estados

Preview:

Badge
        <span class="inline-flex items-center px-3 py-1 rounded-full text-sm font-medium bg-neutral-100 text-neutral-700">
  Badge
</span>
      

Back Up Button

Buttons

Botón para subir al inicio de la página, con animación y hover effects.

Preview:

        
<div
  id="btn-back-up"
  class="fixed right-6 bottom-6 z-50 translate-y-10 scale-90 transform cursor-pointer rounded-full bg-blue-700 p-4 text-white opacity-0 shadow-lg transition-all duration-300 ease-in-out hover:scale-100 hover:bg-blue-600"
>
  <svg xmlns="http://www.w3.org/2000/svg" class="size-4 text-white" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 13a1 1 0 0 0-1-1H5.061a1 1 0 0 1-.75-1.811l6.836-6.835a1.207 1.207 0 0 1 1.707 0l6.835 6.835a1 1 0 0 1-.75 1.811H16a1 1 0 0 0-1 1v6a1 1 0 0 1-1 1h-4a1 1 0 0 1-1-1z"/></svg>
</div>

<script>
  document.addEventListener("astro:page-load", () => {
    const btn = document.querySelector("#btn-back-up") as HTMLElement;
    let isVisible = false;
    let timeoutId: number | null = null;

    const showButton = () => {
      if (timeoutId) {
        clearTimeout(timeoutId);
        timeoutId = null;
      }

      btn.classList.remove("opacity-0", "translate-y-10", "scale-90");
      btn.classList.add("opacity-100", "-translate-y-5", "scale-100");
      isVisible = true;
    };

    const hideButton = () => {
      if (isVisible) {
        btn.classList.remove("opacity-100", "-translate-y-5");
        btn.classList.add("opacity-0", "translate-y-10");

        // Esperar a que termine la animación antes de ocultar completamente
        timeoutId = window.setTimeout(() => {
          btn.classList.add("scale-90");
          isVisible = false;
        }, 300); // Debe coincidir con la duración de la transición (300ms)
      }
    };

    // Manejar el scroll
    const handleScroll = () => {
      // @ts-ignore
      if (window.scrollY >= 300) {
        // Mostrar después de 300px de scroll
        if (!isVisible) showButton();
      } else {
        if (isVisible) hideButton();
      }
    };

    // Manejar clic suave al inicio
    btn.addEventListener("click", (e) => {
      e.preventDefault();
      window.scrollTo({
        top: 0,
        behavior: "smooth",
      });
    });

    // Inicializar el estado del botón
    handleScroll();

    // Escuchar eventos de scroll
    window.addEventListener("scroll", handleScroll, { passive: true });

    // Limpiar el timeout al desmontar
    return () => {
      if (timeoutId) clearTimeout(timeoutId);
      window.removeEventListener("scroll", handleScroll);
    };
  });
</script>

      

WhatsApp Button

Buttons

Botón para WhatsApp, con animación y hover effects. Para agregar el componente se escribe el siguiente código: <WhatsAppButton title="Aqui va el titulo" phone="Aqui va el numero" message="Aqui va el mensaje" />

Preview:

        
---
const { title, phone, message = "" } = Astro.props;
---

<div class="fixed right-6 bottom-6 z-50">
  <div class="group cursor-pointer" aria-label="Boton de WhatsApp">
    <div
      id="btnWhatsapp"
      class="relative flex h-16 w-16 items-center justify-center rounded-full bg-green-500 text-white shadow-lg transition-colors hover:bg-green-600"
    >
      <svg fill="none" viewBox="0 0 360 362" class="size-9"
        ><path
          fill="#ffffff"
          fill-rule="evenodd"
          d="M307.546 52.566C273.709 18.684 228.706.017 180.756 0 81.951 0 1.538 80.404 1.504 179.235c-.017 31.594 8.242 62.432 23.928 89.609L0 361.736l95.024-24.925c26.179 14.285 55.659 21.805 85.655 21.814h.077c98.788 0 179.21-80.413 179.244-179.244.017-47.898-18.608-92.926-52.454-126.807v-.008Zm-126.79 275.788h-.06c-26.73-.008-52.952-7.194-75.831-20.765l-5.44-3.231-56.391 14.791 15.05-54.981-3.542-5.638c-14.912-23.721-22.793-51.139-22.776-79.286.035-82.14 66.867-148.973 149.051-148.973 39.793.017 77.198 15.53 105.328 43.695 28.131 28.157 43.61 65.596 43.593 105.398-.035 82.149-66.867 148.982-148.982 148.982v.008Zm81.719-111.577c-4.478-2.243-26.497-13.073-30.606-14.568-4.108-1.496-7.09-2.243-10.073 2.243-2.982 4.487-11.568 14.577-14.181 17.559-2.613 2.991-5.226 3.361-9.704 1.117-4.477-2.243-18.908-6.97-36.02-22.226-13.313-11.878-22.304-26.54-24.916-31.027-2.613-4.486-.275-6.91 1.959-9.136 2.011-2.011 4.478-5.234 6.721-7.847 2.244-2.613 2.983-4.486 4.478-7.469 1.496-2.991.748-5.603-.369-7.847-1.118-2.243-10.073-24.289-13.812-33.253-3.636-8.732-7.331-7.546-10.073-7.692-2.613-.13-5.595-.155-8.586-.155-2.991 0-7.839 1.118-11.947 5.604-4.108 4.486-15.677 15.324-15.677 37.361s16.047 43.344 18.29 46.335c2.243 2.991 31.585 48.225 76.51 67.632 10.684 4.615 19.029 7.374 25.535 9.437 10.727 3.412 20.49 2.931 28.208 1.779 8.604-1.289 26.498-10.838 30.228-21.298 3.73-10.46 3.73-19.433 2.613-21.298-1.117-1.865-4.108-2.991-8.586-5.234l.008-.017Z"
          clip-rule="evenodd"></path></svg
      >
    </div>
    <div
      id="whatsappMenu"
      class="invisible absolute right-0 bottom-20 w-72 transform overflow-hidden rounded-lg bg-white opacity-0 shadow-lg transition-all duration-300"
    >
      <div class="flex items-center gap-2 bg-[#1EA951] p-4 text-white">
        <div class="rounded-full bg-white/20 p-1.5">
          <svg fill="none" viewBox="0 0 360 362" class="size-5"
            ><path
              fill="#ffffff"
              fill-rule="evenodd"
              d="M307.546 52.566C273.709 18.684 228.706.017 180.756 0 81.951 0 1.538 80.404 1.504 179.235c-.017 31.594 8.242 62.432 23.928 89.609L0 361.736l95.024-24.925c26.179 14.285 55.659 21.805 85.655 21.814h.077c98.788 0 179.21-80.413 179.244-179.244.017-47.898-18.608-92.926-52.454-126.807v-.008Zm-126.79 275.788h-.06c-26.73-.008-52.952-7.194-75.831-20.765l-5.44-3.231-56.391 14.791 15.05-54.981-3.542-5.638c-14.912-23.721-22.793-51.139-22.776-79.286.035-82.14 66.867-148.973 149.051-148.973 39.793.017 77.198 15.53 105.328 43.695 28.131 28.157 43.61 65.596 43.593 105.398-.035 82.149-66.867 148.982-148.982 148.982v.008Zm81.719-111.577c-4.478-2.243-26.497-13.073-30.606-14.568-4.108-1.496-7.09-2.243-10.073 2.243-2.982 4.487-11.568 14.577-14.181 17.559-2.613 2.991-5.226 3.361-9.704 1.117-4.477-2.243-18.908-6.97-36.02-22.226-13.313-11.878-22.304-26.54-24.916-31.027-2.613-4.486-.275-6.91 1.959-9.136 2.011-2.011 4.478-5.234 6.721-7.847 2.244-2.613 2.983-4.486 4.478-7.469 1.496-2.991.748-5.603-.369-7.847-1.118-2.243-10.073-24.289-13.812-33.253-3.636-8.732-7.331-7.546-10.073-7.692-2.613-.13-5.595-.155-8.586-.155-2.991 0-7.839 1.118-11.947 5.604-4.108 4.486-15.677 15.324-15.677 37.361s16.047 43.344 18.29 46.335c2.243 2.991 31.585 48.225 76.51 67.632 10.684 4.615 19.029 7.374 25.535 9.437 10.727 3.412 20.49 2.931 28.208 1.779 8.604-1.289 26.498-10.838 30.228-21.298 3.73-10.46 3.73-19.433 2.613-21.298-1.117-1.865-4.108-2.991-8.586-5.234l.008-.017Z"
              clip-rule="evenodd"></path></svg
          >
        </div>
        <span class="font-semibold">{title}</span>
      </div>
      <div class="space-y-3 bg-gray-100 p-4">
        <p class="rounded-lg bg-white p-3 text-sm text-gray-700">
          Hola👋, ¿Cómo podemos ayudarte?
        </p>
        <a
          href="https://wa.me/1" + phone + "?text=" + message
          target="_blank"
          rel="noopener noreferrer"
          class="inline-flex items-center gap-2 rounded-lg bg-green-500 px-4 py-2 text-sm font-medium text-white transition-colors hover:bg-green-600"
        >
          <span>Abrir chat</span>
          <svg
            xmlns="http://www.w3.org/2000/svg"
            width="24"
            height="24"
            viewBox="0 0 24 24"
            fill="none"
            stroke="currentColor"
            stroke-width="2"
            stroke-linecap="round"
            stroke-linejoin="round"
            class="size-4 text-white"
            ><path
              d="M14.536 21.686a.5.5 0 0 0 .937-.024l6.5-19a.496.496 0 0 0-.635-.635l-19 6.5a.5.5 0 0 0-.024.937l7.93 3.18a2 2 0 0 1 1.112 1.11z"
            ></path><path d="m21.854 2.147-10.94 10.939"></path></svg
          >
        </a>
      </div>
    </div>
    <div
      id="btnToastify"
      class="invisible absolute right-20 bottom-0 w-56 transform overflow-hidden rounded-lg bg-white opacity-0 shadow-lg transition-all duration-300 group-hover:visible group-hover:-translate-y-2 group-hover:opacity-100"
    >
      <div class="flex items-center gap-2 bg-[#1EA951] p-2 text-white">
        <div class="rounded-full bg-white/20 p-1">
          <svg fill="none" viewBox="0 0 360 362" class="size-4"
            ><path
              fill="#ffffff"
              fill-rule="evenodd"
              d="M307.546 52.566C273.709 18.684 228.706.017 180.756 0 81.951 0 1.538 80.404 1.504 179.235c-.017 31.594 8.242 62.432 23.928 89.609L0 361.736l95.024-24.925c26.179 14.285 55.659 21.805 85.655 21.814h.077c98.788 0 179.21-80.413 179.244-179.244.017-47.898-18.608-92.926-52.454-126.807v-.008Zm-126.79 275.788h-.06c-26.73-.008-52.952-7.194-75.831-20.765l-5.44-3.231-56.391 14.791 15.05-54.981-3.542-5.638c-14.912-23.721-22.793-51.139-22.776-79.286.035-82.14 66.867-148.973 149.051-148.973 39.793.017 77.198 15.53 105.328 43.695 28.131 28.157 43.61 65.596 43.593 105.398-.035 82.149-66.867 148.982-148.982 148.982v.008Zm81.719-111.577c-4.478-2.243-26.497-13.073-30.606-14.568-4.108-1.496-7.09-2.243-10.073 2.243-2.982 4.487-11.568 14.577-14.181 17.559-2.613 2.991-5.226 3.361-9.704 1.117-4.477-2.243-18.908-6.97-36.02-22.226-13.313-11.878-22.304-26.54-24.916-31.027-2.613-4.486-.275-6.91 1.959-9.136 2.011-2.011 4.478-5.234 6.721-7.847 2.244-2.613 2.983-4.486 4.478-7.469 1.496-2.991.748-5.603-.369-7.847-1.118-2.243-10.073-24.289-13.812-33.253-3.636-8.732-7.331-7.546-10.073-7.692-2.613-.13-5.595-.155-8.586-.155-2.991 0-7.839 1.118-11.947 5.604-4.108 4.486-15.677 15.324-15.677 37.361s16.047 43.344 18.29 46.335c2.243 2.991 31.585 48.225 76.51 67.632 10.684 4.615 19.029 7.374 25.535 9.437 10.727 3.412 20.49 2.931 28.208 1.779 8.604-1.289 26.498-10.838 30.228-21.298 3.73-10.46 3.73-19.433 2.613-21.298-1.117-1.865-4.108-2.991-8.586-5.234l.008-.017Z"
              clip-rule="evenodd"></path></svg
          >
        </div>
        <span class="text-sm font-semibold">Envianos un mensaje</span>
      </div>
    </div>
  </div>
</div>

<script>
  document.addEventListener("astro:page-load", () => {
    let btnWhatsapp = document.getElementById("btnWhatsapp") as HTMLDivElement;
    let whatsappMenu = document.getElementById(
      "whatsappMenu",
    ) as HTMLDivElement;

    if (btnWhatsapp && whatsappMenu) {
      btnWhatsapp.addEventListener("click", () => {
        whatsappMenu.classList.toggle("opacity-0");
        whatsappMenu.classList.toggle("invisible");
        whatsappMenu.classList.toggle("-translate-y-2");
      });
    }
  });
</script>