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-familyClaro 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);
}/* 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; }/* 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; }
}