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-slotdata-statedata-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,slotPropso la sustitución de un slot - sigues queriendo el router, la página de conversación y el compositor por defecto
Siguiente paso
- Ajústalo a tu marca para colores, radio y modo oscuro
- Páginas y layouts cuando necesites páginas propias o integrarlo en línea
¿Te resultó útil esta página?
Abre una incidencia de documentación ya rellenada para que el equipo pueda actuar.

