Saltar al contenido principal

Cambia una sola cosa

Mantén el widget por defecto y sustituye una pieza pequeña cada vez.

Support está pensado para cambios pequeños. Empieza por los estilos, luego sustituye un componente y deja que el resto del widget siga funcionando igual.

Los ejemplos TSX usan utilidades de Tailwind por brevedad. Tailwind no es obligatorio: sustituye esos nombres de clase por tu propio CSS cuando uses el punto de entrada precompilado @fluxolat/react/styles.css.

Usa esto cuando

  • quieres el widget en producción rápido
  • necesitas que la burbuja o la primera pantalla se parezcan más a tu producto
  • quieres sustituir cosas sin riesgo, sin rehacer el router ni la interfaz de conversación

El cambio más pequeño que funciona

import { Support } from "@fluxolat/react";
 
<Support
  classNames={{
    trigger: "bg-black text-white",
    content: "border-neutral-200 shadow-2xl",
  }}
  slotProps={{
    content: {
      className: "border border-neutral-200 shadow-2xl",
    },
  }}
/>;

Usa classNames para el disparador y el contenido integrados. Usa slotProps cuando quieras pasar props de presentación adicionales a las partes integradas.

El widget por defecto también expone puntos de estilo estables:

  • data-slot
  • data-state
  • data-page
[data-slot="trigger"][data-state="open"] {
  transform: scale(1.02);
}
 
[data-slot="content"] {
  backdrop-filter: blur(12px);
}

Cuando sustituyes un slot, heredas sus responsabilidades de accesibilidad. Conserva la ref reenviada y las props del botón, mantén el nombre accesible y los estilos de foco del disparador, haz que el área sea de al menos 44 × 44 píxeles CSS y anuncia los mensajes sin leer con un texto con sentido cuando le importen al usuario.

Ejemplo de burbuja 1

Usa slots.trigger cuando lo único que quieras cambiar sea el lanzador.

import { Support, type SupportTriggerSlotProps } from "@fluxolat/react";
import * as React from "react";
 
function mergeClassNames(...classes: Array<string | undefined>) {
  return classes.filter(Boolean).join(" ");
}
 
const ClassicBubble = React.forwardRef<HTMLButtonElement, SupportTriggerSlotProps>(
  function ClassicBubbleTrigger(
    { className, isOpen, isTyping: _isTyping, toggle, unreadCount, ...props },
    ref
  ) {
    return (
      <button
        {...props}
        className={mergeClassNames(
          "relative flex size-14 items-center justify-center border border-black bg-black font-medium text-white text-sm shadow-xl transition-transform hover:scale-[1.02]",
          className
        )}
        onClick={toggle}
        ref={ref}
        type="button"
      >
        {isOpen ? "Close" : "Chat"}
        {unreadCount > 0 ? (
          <span className="-right-1 -top-1 absolute flex size-5 items-center justify-center border border-white bg-orange-500 text-[11px]">
            {unreadCount}
          </span>
        ) : null}
      </button>
    );
  }
);
 
<Support slots={{ trigger: ClassicBubble }} />;

Ejemplo de burbuja 2

Ese mismo slot puede parecerse más a un botón dentro del producto que a una burbuja de chat flotante.

import { Support, type SupportTriggerSlotProps } from "@fluxolat/react";
import * as React from "react";
 
function mergeClassNames(...classes: Array<string | undefined>) {
  return classes.filter(Boolean).join(" ");
}
 
const PillBubble = React.forwardRef<HTMLButtonElement, SupportTriggerSlotProps>(
  function PillBubble(
    {
      className,
      isOpen: _isOpen,
      isTyping,
      unreadCount: _unreadCount,
      toggle,
      ...props
    },
    ref
  ) {
    return (
      <button
        {...props}
        className={mergeClassNames(
          "flex h-12 items-center gap-2 border border-black bg-white px-4 font-medium text-black text-sm shadow-xl transition-transform hover:scale-[1.01]",
          className
        )}
        onClick={toggle}
        ref={ref}
        type="button"
      >
        <span className="size-2 bg-orange-500" />
        <span>{isTyping ? "Support is typing..." : "Open support"}</span>
      </button>
    );
  }
);
 
<Support slots={{ trigger: PillBubble }} />;

Sustituir la primera pantalla

Mantén el flujo de conversación por defecto y cambia solo la pantalla de inicio.

import { Support, type SupportHomePageSlotProps } from "@fluxolat/react";
 
function CustomHomePage({
  className,
  openConversationHistory,
  quickOptions,
  startConversation,
  website,
}: SupportHomePageSlotProps) {
  return (
    <div className={className}>
      <h2>{website?.name}</h2>
      <p>Rewrite the first screen while keeping the default conversation flow.</p>
 
      {quickOptions.map((option) => (
        <button key={option} onClick={() => startConversation(option)} type="button">
          {option}
        </button>
      ))}
 
      <button onClick={openConversationHistory} type="button">
        View past conversations
      </button>
    </div>
  );
}
 
<Support
  slotProps={{
    content: {
      className: "border shadow-2xl",
    },
  }}
  slots={{ homePage: CustomHomePage }}
/>;

Fluxo

Real support, instantly.

Ask about onboarding, setup, billing, or migration without leaving the product.

Cuándo quedarte aquí

  • tu widget ya está en producción
  • los cambios de marca caben en classNames, slotProps o la sustitución de un slot
  • sigues queriendo el router, la página de conversación y el compositor por defecto

Siguiente paso

¿Te resultó útil esta página?

Abre una incidencia de documentación ya rellenada para que el equipo pueda actuar.