saltar al contenido principal
Explorar la documentación

CSS personalizado

La vía de escape: reestiliza cualquier superficie del widget con CSS sin procesar cuando los controles de tokens del estudio no alcanzan.

Los controles de tokens del Widget Design Studio cubren la mayoría de las necesidades de marca: se mantienen seguros para AA y sobreviven a las actualizaciones del widget. Cuando no alcanzan, cada diseño incluye un campo de CSS personalizado (paso General): CSS sin procesar inyectado en el Shadow DOM del widget, dirigido a los selectores estables y a las propiedades personalizadas --syncanix-* documentados en esta página.

Cómo se aplica

El CSS se valida mientras escribes y se revalida en el servidor al guardar. Entra en vigor cuando guardas el diseño; si ese diseño es el que está en uso, los widgets incrustados recogen el cambio en su próxima carga de configuración, en unos minutos.

Una sola cadena de CSS por diseño: se aplica en todos los tamaños del widget y en ambos esquemas de color (delimita las reglas solo para oscuro con el selector de más abajo), y las reglas de tema por página nunca llevan su propio CSS personalizado.

Tu CSS gana la cascada

El widget inyecta tu CSS como la última hoja de estilos de su Shadow DOM, después de todos los estilos integrados. Por tanto, una regla de igual especificidad anula la del widget — sin necesidad de !important para un reestilizado normal.

/* Does NOT work — tokens are applied inline on the host element,
   which beats any :host rule: */
:host { --syncanix-primary: #0f766e; }

/* Works — re-declare the variable on a descendant instead: */
.syncanix-panel { --syncanix-primary: #0f766e; }

Selectores estables

Estos selectores son un contrato documentado y estable — fijado con tests, de modo que una versión del widget no puede renombrarlos en silencio.

/* Launcher (the closed floating button — an attribute, not a class) */
[data-syncanix='launcher']
.syncanix-launcher-avatar
.syncanix-launcher-brand

/* Panel chrome */
.syncanix-panel
.syncanix-panel-header

/* Messages */
.syncanix-panel-item-user
.syncanix-panel-item-assistant
.syncanix-msg-body

/* Composer */
.syncanix-panel-composer
.syncanix-panel-composer-form
.syncanix-panel-composer-input
.syncanix-panel-composer-submit
.syncanix-panel-composer-stop
.syncanix-panel-composer-limit

/* Rich primitives — each renders with its type on the root */
.syncanix-card
.syncanix-confirm-card
[data-syncanix-primitive='list' | 'table' | 'card' | 'markdown' | 'button'
  | 'detail' | 'form' | 'status' | 'empty-state' | 'confirm-card' | 'navigate'
  | 'component' | 'iframe' | 'action-plan' | 'action-in-progress'
  | 'action-result' | 'chart' | 'embed' | 'metric' | 'funnel' | 'flow'
  | 'sign-in-card' | 'onboarding-checklist']

Propiedades personalizadas

Cada superficie del widget se pinta a partir de propiedades personalizadas --syncanix-* con espacio de nombres, así que redeclarar una en un subárbol reestiliza solo ese subárbol. El atributo de incrustación data-theme acepta los mismos nombres de token — consulta Tematización del widget para ver cómo se componen las capas del tema.

/* Colour */
--syncanix-primary            --syncanix-primary-foreground
--syncanix-background         --syncanix-foreground
--syncanix-muted              --syncanix-muted-foreground
--syncanix-border             --syncanix-ring
--syncanix-destructive        --syncanix-destructive-foreground
--syncanix-link

/* Typography */
--syncanix-font-family        --syncanix-font-family-heading
--syncanix-line-height-base   --syncanix-letter-spacing-base
--syncanix-measure

/* Shape */
--syncanix-radius             --syncanix-radius-sm
--syncanix-radius-md          --syncanix-radius-lg
--syncanix-radius-full        --syncanix-avatar-radius

/* Elevation, spacing, motion, icons */
--syncanix-shadow-lg          --syncanix-shadow-xl
--syncanix-spacing            --syncanix-spacing-sm
--syncanix-motion-duration    --syncanix-motion-easing
--syncanix-icon-stroke-width

/* Per-element studio overrides (set on a descendant to override locally) */
--syncanix-launcher-bg        --syncanix-launcher-fg
--syncanix-header-bg          --syncanix-header-fg
--syncanix-user-bubble-bg     --syncanix-user-bubble-fg
--syncanix-assistant-bubble-bg  --syncanix-assistant-bubble-fg
--syncanix-composer-bg        --syncanix-pane-bg
--syncanix-ai-font-family     --syncanix-user-font-family

Claro y oscuro

El esquema de color resuelto se estampa en el host del widget como data-color-scheme. Tu CSS se aplica en ambos esquemas — delimita las reglas solo para oscuro con :host([data-color-scheme='dark']).

.syncanix-panel-header { background: #f8fafc; }

:host([data-color-scheme='dark']) .syncanix-panel-header {
  background: #1e293b;
}

Qué está bloqueado

El CSS personalizado se valida en el editor, al guardar y de nuevo en el widget antes de inyectarse. El validador rechaza:

  • @import — obtención o exfiltración de CSS externo.
  • expression(), URLs javascript: y data:text/html, behavior:, -moz-binding — vectores heredados de inyección de scripts.
  • Referencias url() externas — un vector de baliza de red / fuga de datos. Incrusta los recursos (incluidos los archivos de fuentes) como URI data:.
  • Una etiqueta de cierre </style> — un escape del Shadow DOM.
  • Ocultar o reestilizar el aviso «hecho con IA» (selectores syncanix-ai-* / syncanix-first-message-*) — una superficie regulatoria bloqueada.
  • Más de 64 KB de CSS por diseño.

Ejemplos

/* A gradient panel header with a hairline divider */
.syncanix-panel-header {
  background: linear-gradient(135deg, #0f766e, #134e4a);
  border-block-end: 1px solid rgba(255, 255, 255, 0.12);
}
Reestilizar la cabecera del panel
/* Round only the cards, and give tables a tighter radius */
[data-syncanix-primitive='card'] { --syncanix-radius: 1rem; }
[data-syncanix-primitive='table'] { --syncanix-radius: 0.25rem; }
Anular un token solo para una primitiva
/* Slow the widget's motion down, and switch it off for
   reduced-motion visitors */
.syncanix-panel { --syncanix-motion-duration: 300ms; }

@media (prefers-reduced-motion: reduce) {
  .syncanix-panel { --syncanix-motion-duration: 0ms; }
}
Ajustar el movimiento respetando reduced-motion

Próximos pasos