npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

gq-chatbot-widget

v1.5.0

Published

Web Component de chat creado con React, TypeScript y Tailwind.

Readme

GQ Chatbot Widget

Web Component de chat premium, creado con React + TypeScript + Framer Motion, diseñado para integrarse en cualquier sitio con una sola etiqueta HTML.

Qué incluye

  • Launcher animado con estados cerrado, peek y chat abierto.
  • Chat interactivo con animaciones por mensaje, timestamps y autoscroll.
  • Modal de términos y condiciones antes de abrir la conversación.
  • Botón opcional de WhatsApp con plantilla de mensaje y placeholders.
  • Personalización visual avanzada por atributos (colores de panel, burbujas, launcher, input y más).
  • Borde con gradiente animado en launcher y panel (activable, con dos colores configurables).
  • Scrollbar personalizado en la lista de mensajes (Chrome, Safari, Edge y Firefox), con colores configurables.
  • Sin Tailwind preflight global (no resetea *, html, body del sitio host).
  • Shadow DOM opcional (use-shadow / shadow) para inyectar estilos solo dentro del widget (recomendado en Next.js App Router sin iframe).
  • SSR-safe: el registro del custom element no hace nada sin window / customElements. Entry opcional gq-chatbot-widget/client para registrar solo en cliente.

Instalación

npm install gq-chatbot-widget

Uso rápido

Con bundler (React, Vite, Next, etc.)

import 'gq-chatbot-widget'
<gq-chatbot-widget
  agent-id="agent_0701kp9thvhvevbt2p9tastrz2q7"
  agent-name="Pipi"
  theme-color="#2563eb"
></gq-chatbot-widget>

Con CDN

<script src="https://unpkg.com/[email protected]/dist/chat-widget.umd.js"></script>

<gq-chatbot-widget
  agent-id="agent_0701kp9thvhvevbt2p9tastrz2q7"
  agent-name="Pipi"
  theme-color="#2563eb"
></gq-chatbot-widget>

Next.js (App Router) sin iframe

Problema que resuelve

En versiones anteriores el CSS del bundle podía afectar el sitio (p. ej. preflight de Tailwind). Desde v1.5.0:

  1. El CSS del paquete no incluye preflight (@tailwind base eliminado): no se resetean *, html ni body del documento.
  2. Con use-shadow="true" o shadow="open" (o shadow="closed"), el widget usa Shadow DOM: todo el CSS compilado va en un <style> dentro del shadowRoot, no en document.head, así no “pisa” estilos del layout.
  3. El módulo principal es seguro en SSR: si Next evalúa el import en el servidor, registerGqChatbotWidget() no ejecuta customElements.define sin window.

Recomendado: etiqueta con Shadow DOM

// app/layout.tsx (Server Component está bien: solo HTML estático)
export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="es">
      <body>
        {children}
        <script
          src="https://unpkg.com/[email protected]/dist/chat-widget.umd.js"
          defer
        />
        <gq-chatbot-widget
          use-shadow="true"
          agent-id="tu-agent-id"
          agent-name="Pipi"
          theme-color="#0379D5"
        />
      </body>
    </html>
  )
}

Equivalente semántico: shadow="open" o shadow="closed". El atributo vacío shadow en HTML5 suele leerse como cadena vacía y el widget lo trata como modo open.

Importante: definí use-shadow / shadow antes del primer render del nodo (p. ej. en el HTML inicial). No se soporta pasar de light DOM a shadow después de conectar el elemento.

Opción: solo cliente + registro explícito

Si preferís importar desde un Client Component o useEffect:

'use client'

import { useEffect } from 'react'

export function GqChatbotLoader() {
  useEffect(() => {
    void import('gq-chatbot-widget/client').then(({ registerGqChatbotWidget }) => {
      registerGqChatbotWidget()
    })
  }, [])
  return null
}

Luego colocá <gq-chatbot-widget use-shadow="true" agent-id="..." /> en el árbol. El entry gq-chatbot-widget/client solo exporta registerGqChatbotWidget (no registra al importar), ideal para evitar side effects en el servidor.

Import único (auto-registro en cliente)

'use client'
import 'gq-chatbot-widget'

En Server Components, no hagas import 'gq-chatbot-widget' en el módulo del servidor: usá la etiqueta + <script> como arriba, o un client boundary con import('gq-chatbot-widget').

Autocompletado en el editor (HTML)

VS Code y Cursor pueden sugerir atributos del custom element usando html.customData.

En este repositorio

Ya está configurado en .vscode/settings.json apuntando a .vscode/gq-chatbot-widget.html-data.json.

Si alguien instala el paquete por npm

El archivo publicado vive en:

node_modules/gq-chatbot-widget/editor/gq-chatbot-widget.html-data.json

En el proyecto consumidor, agrega en .vscode/settings.json (o en tu settings.json de usuario):

{
  "html.customData": [
    "./node_modules/gq-chatbot-widget/editor/gq-chatbot-widget.html-data.json"
  ]
}

Reiniciá el editor o recargá la ventana si no aparece de inmediato.

En proyectos React / TypeScript (JSX)

El paquete publica tipos en dist/gq-chatbot-widget.d.ts y declara "types" + "exports.types" en package.json.

Eso significa que, en un proyecto consumidor con npm install gq-chatbot-widget, al escribir <gq-chatbot-widget /> en .tsx el editor debería sugerir atributos sin copiar un global.d.ts manual, siempre que el proyecto tenga @types/react instalado (porque los tipos referencian react).

Si no ves sugerencias de inmediato: recargá la ventana del editor o verificá que tu tsconfig incluya los archivos donde usás el widget.

API de atributos (qué edita cada uno)

Identidad y comportamiento base

  • agent-id (requerido): identificador interno del agente (persistencia por agente, plantillas, etc.).
  • agent-name: nombre visible del asistente en bienvenida, avatar y placeholders ({name}).
  • theme-color: color de acento principal (botón enviar, focos, puntos y elementos destacados).
  • use-shadow: true → Shadow DOM con attachShadow({ mode: 'open' }) y CSS solo dentro del shadow (recomendado en Next sin iframe).
  • shadow: open | closed; también activa Shadow DOM (vacío = open). Alternativa a use-shadow="true".

Webhook (chat remoto por HTTP POST)

  • chat-webhook-url: URL del webhook que recibe JSON { "userMessage", "sessionId" }. Si está vacío, el chat usa respuesta simulada.
  • chat-api-key: valor del header x-api-key en el POST (sensible en HTML público; en producción preferí un proxy en tu backend).
  • session-id: opcional; si se omite, el front genera un UUID y lo guarda en sessionStorage por agent-id.

WhatsApp

  • whatsapp-enabled: true/false; habilita u oculta el botón de WhatsApp en el launcher.
  • whatsapp-phone: número internacional sin + ni espacios (ej: 5491122334455).
  • whatsapp-template: plantilla del mensaje para WhatsApp.
    • Placeholders soportados: {name}, {topic}, {agentId}.
    • Se aplica encodeURIComponent automáticamente.
    • Si whatsapp-phone es inválido, el botón queda deshabilitado y se muestra warning en consola.

Panel y área de conversación

  • panel-background: fondo global del contenedor del chat.
  • header-background: fondo de la barra superior del chat.
  • messages-background: fondo del área donde se renderizan los mensajes.
  • messages-scrollbar-thumb-color: color del “thumb” del scrollbar vertical de la lista de mensajes (cualquier color CSS). Compatible con Chrome, Edge (motor Chromium), Safari (WebKit) vía ::-webkit-scrollbar, y Firefox vía scrollbar-color / scrollbar-width: thin.
  • messages-scrollbar-track-color: color de la pista del scrollbar (opcional; por defecto un gris muy suave).
  • assistant-bubble-background: color de burbuja del bot.
  • assistant-bubble-text-color: color de texto dentro de burbujas del bot.
  • user-bubble-background: color de burbuja del usuario.
  • user-bubble-text-color: color de texto dentro de burbujas del usuario.

Input de mensaje

  • input-wrapper-background: fondo del borde exterior del input.
  • input-background: fondo interno del campo de texto.
  • input-text-color: color del texto escrito por el usuario.
  • input-placeholder-color: color del placeholder del input.
  • input-border-color: color del borde del campo de escritura.

Launcher (botón/barra inferior)

  • launcher-background: fondo del launcher.
  • launcher-border-color: color del borde del launcher.
  • launcher-text-color: color de texto e íconos del launcher.
  • launcher-secondary-background: fondo de la pastilla ¿Necesitas ayuda?.
  • launcher-cta-background: fondo del botón CTA principal.
  • launcher-cta-text-color: color de texto del CTA principal.

Borde con gradiente (launcher + panel abierto)

El anillo animado recorre el perímetro del launcher (círculo y barra “peek”) y del panel de chat cuando está abierto.

  • gradient-border-enabled: true (por defecto) o false. Desactiva por completo el efecto (sin animación ni anillo de 2px).
  • gradient-border-from: primer color del gradiente (cualquier color CSS válido, p. ej. #0084d1).
  • gradient-border-to: segundo color (p. ej. #0047bb).

Si el visitante tiene preferencia de movimiento reducido (prefers-reduced-motion), el borde animado no se muestra aunque gradient-border-enabled sea true (se usa el mismo chrome sólido que con el borde desactivado).

Ejemplo:

<gq-chatbot-widget
  agent-id="mi-agente"
  gradient-border-enabled="true"
  gradient-border-from="#0084d1"
  gradient-border-to="#0047bb"
></gq-chatbot-widget>

Scrollbar de la lista de mensajes

El área con scroll usa la clase .gq-messages-scroll: barra fina (7px en WebKit), thumb redondeado con margen visual (background-clip: padding-box) y estados :hover / :active discretos.

Si no pasás atributos, el thumb toma un azul semitransparente acorde al tema por defecto del widget.

Ejemplo completo

<gq-chatbot-widget
  agent-id="agent_0701kp9thvhvevbt2p9tastrz2q7"
  agent-name="Pipi"
  theme-color="#0ea5e9"
  whatsapp-enabled="true"
  whatsapp-phone="5491122334455"
  whatsapp-template="Hola! Soy {name}. Necesito ayuda con {topic}. ID: {agentId}"
  panel-background="#0f1115"
  header-background="#151922"
  messages-background="#151922"
  messages-scrollbar-thumb-color="rgba(14, 165, 233, 0.45)"
  messages-scrollbar-track-color="rgba(255, 255, 255, 0.06)"
  assistant-bubble-background="#232a38"
  assistant-bubble-text-color="#e6edf8"
  user-bubble-background="#0ea5e9"
  user-bubble-text-color="#ffffff"
  input-wrapper-background="#20283a"
  input-background="#0d121c"
  input-text-color="#d6deeb"
  input-placeholder-color="#8b97ad"
  input-border-color="#2f3a52"
  launcher-background="rgba(10,12,18,0.92)"
  launcher-border-color="rgba(148,163,184,0.25)"
  launcher-text-color="#e6edf8"
  launcher-secondary-background="rgba(148,163,184,0.14)"
  launcher-cta-background="#0ea5e9"
  launcher-cta-text-color="#ffffff"
  gradient-border-enabled="true"
  gradient-border-from="#0084d1"
  gradient-border-to="#0047bb"
></gq-chatbot-widget>

Desarrollo local

npm install
npm run dev

Webhook y API key desde .env.local (recomendado en este repo)

Para no hardcodear URL ni clave en index.html, usá variables solo en desarrollo (Vite las expone al cliente si empiezan con VITE_):

  1. Copiá .env.example a .env.local en la raíz del proyecto (ese archivo está cubierto por *.local en .gitignore y no debería subirse a git).
  2. Completá al menos:
    • VITE_CHAT_WEBHOOK_URL: la URL de tu webhook o una ruta relativa del mismo origen que use el proxy de Vite (ver abajo).
    • VITE_CHAT_API_KEY: misma clave que enviarías como header x-api-key al webhook.
  3. Reiniciá npm run dev cada vez que cambies .env.local.

Proxy en desarrollo vs URL absoluta

En npm run dev el front suele servirse desde localhost con un puerto fijo. Si el widget hace fetch a otro origen (otro dominio o puerto), el navegador aplica CORS; el servidor del webhook tiene que responder con cabeceras Access-Control-Allow-Origin acordes, o aparecerán errores tipo “blocked by CORS policy”.

Dos enfoques habituales:

  • Proxy en Vite: en .env.local usás una ruta relativa del mismo origen que la app de desarrollo (por ejemplo /api/mi-webhook); en vite.config.ts configurás el proxy para reenviar esa ruta al host y path reales del webhook. El navegador solo habla con el servidor de Vite, así evitás CORS en local.
  • URL absoluta del webhook: podés poner en VITE_CHAT_WEBHOOK_URL la URL completa del endpoint, siempre que ese servidor permita explícitamente el origen de tu entorno de desarrollo.

La ruta del proxy, el host y el path del webhook los definís vos según tu stack; usá vite.config.ts y .env.example como referencia y adaptalos a tu despliegue. Podés anotar la URL real en comentarios dentro de .env.local para no perder el contexto.

Prioridad: si el elemento <gq-chatbot-widget> tiene los atributos chat-webhook-url o chat-api-key, esos valores pisan lo definido en .env.local (útil para pruebas puntuales).

En producción (sitio embebido sin Vite), las variables VITE_* no existen: configurá chat-webhook-url y chat-api-key en el HTML, o mejor, un endpoint propio que haga de proxy y oculte la clave.

Build

npm run build

Archivos generados en dist/:

  • chat-widget.umd.js
  • chat-widget.es.js

Publicación en npm

npm login --auth-type=web
npm publish --access public