SolandaUI Web Components · v1.0.0
Solanda Social Catppuccin Gruvbox Tokyo Nord Claro Oscuro Sistema

SolandaUI

Biblioteca de Web Components sin dependencias de framework. El nombre viene del Barrio Solanda (Quito, Ecuador): un proyecto planificado en 1984 que creció desbordando sus propios límites — como todo buen sistema de diseño que termina siendo adoptado, extendido y llevado más lejos de lo que sus autores previeron.

La paleta de colores se extrae de la materialidad del barrio: ladrillo terracota, fachadas amarillas, concreto andino, muros encalados y el cielo azulado de las noches quiteñas. Compatible con cualquier stack: HTML puro, Vue, React, Svelte, Astro.

Web Components nativos Shadow DOM CSS tokens 6 temas incluidos 37 componentes

instalación

Importa los tokens CSS globalmente y los componentes que necesites como módulos ES.

npm install @federa/solanda-ui
import '@federa/solanda-ui/css'
import '@federa/solanda-ui/sl-button' import '@federa/solanda-ui/sl-input' // … importa solo los que uses
<sl-button variant="default">Hola mundo</sl-button>
import '@federa/solanda-ui/css/themes/social-neutral' import '@federa/solanda-ui/css/themes/catppuccin' import '@federa/solanda-ui/css/themes/gruvbox' import '@federa/solanda-ui/css/themes/tokyo-night' import '@federa/solanda-ui/css/themes/nord'
import { ThemeManager } from '@federa/solanda-ui/theme' const theme = ThemeManager.init({ storageKey: 'my-app-theme', defaultPreset: 'solanda', // 'solanda' | 'social-neutral' | 'catppuccin' | 'gruvbox' | 'tokyo-night' | 'nord' defaultTheme: 'system', // 'light' | 'dark' | 'system' autoApply: true }) theme.setTheme('dark') theme.setPreset('catppuccin')

Button sl-button

Elemento de acción primario. Soporta múltiples variantes visuales, tamaños y estados.

Variantes Default Secondary Outline Ghost Link Destructive
Tamaños XS Small Default Large
Estados Normal Disabled

Ultimo clic:

<sl-button variant="default" size="default">Acción</sl-button> <!-- Con icono --> <sl-button icon="star" icon-position="left" label="Guardar"></sl-button> <!-- Escuchar clic --> <script> document.querySelector('sl-button').addEventListener('click', (e) => { console.log(e.detail.originalEvent) }) </script>
AtributoTipoPor defectoDescripción
variantstringdefaultdefault · secondary · outline · ghost · link · destructive
sizestringdefaultxs · sm · default · lg · icon
disabledbooleanfalseDeshabilita el botón
typestringbuttonbutton · submit · reset
iconstringNombre de icono (requiere sl-icon)
icon-positionstringleftleft · right
labelstringTexto alternativo al slot
valuestringValor para uso en button-group
EventoDetailDescripción
click{ originalEvent: MouseEvent }Se dispara al hacer clic. Reemplaza el evento nativo con uno compuesto.

Button Group sl-button-group

Agrupa botones con bordes compartidos. Soporta modo radio (selección única) y checkbox (selección múltiple).

Horizontal Izquierda Centro Derecha
Vertical Arriba Medio Abajo
Radio Lista Cuadrícula Tabla
Checkbox N I S

Radio: grid  ·  Checkbox:

<!-- Grupo básico --> <sl-button-group> <sl-button variant="outline">A</sl-button> <sl-button variant="outline">B</sl-button> </sl-button-group> <!-- Modo radio --> <sl-button-group type="radio" value="b"> <sl-button variant="outline" value="a">A</sl-button> <sl-button variant="outline" value="b">B</sl-button> </sl-button-group> <!-- Evento --> <script> document.querySelector('sl-button-group').addEventListener('sl-buttongroup-change', (e) => { console.log(e.detail.value) // string o string[] }) </script>
AtributoTipoPor defectoDescripción
orientationstringhorizontalhorizontal · vertical
typestringradio · checkbox. Sin valor, es solo visual.
valuestringValor activo inicial (radio) o valores separados por coma (checkbox)
sizestringPropaga tamaño a todos los botones hijos

Input sl-input

Campo de texto de una línea. Envuelve el elemento nativo <input> con estilos de tokens y eventos normalizados.

Texto
Email
Contraseña
Deshabilitado
Solo lectura

Valor:

<sl-input type="email" placeholder="tu@email.com" required></sl-input> <script> document.querySelector('sl-input').addEventListener('input', (e) => { console.log(e.detail.value) }) </script>
AtributoTipoPor defectoDescripción
typestringtextTipo de input nativo: text · email · password · number · file · etc.
valuestringValor del campo
placeholderstringTexto placeholder
disabledbooleanfalseDeshabilita el input
readonlybooleanfalseSolo lectura
requiredbooleanfalseCampo obligatorio
namestringNombre para formularios nativos

Textarea sl-textarea

Campo de texto multilínea. Misma API que sl-input con soporte para filas y redimensionado.

Descripción
Solo lectura
Deshabilitado
<sl-textarea placeholder="Descripción del producto…" rows="5" name="description" ></sl-textarea>
AtributoTipoPor defectoDescripción
valuestringContenido del textarea
placeholderstringTexto placeholder
rowsnumber3Número de filas visibles
disabledbooleanfalseDeshabilita el campo
readonlybooleanfalseSolo lectura
namestringNombre para formularios

Select sl-select

Selector desplegable. Las opciones se pasan como JSON en el atributo options.

Framework
Con opción deshabilitada
Deshabilitado

Seleccionado:

<sl-select placeholder="Elige una opción…" options='[ { "value": "a", "label": "Opción A" }, { "value": "b", "label": "Opción B" }, { "value": "c", "label": "Deshabilitada", "disabled": true } ]' ></sl-select> <script> document.querySelector('sl-select').addEventListener('change', (e) => { console.log(e.detail.value) }) </script>
AtributoTipoPor defectoDescripción
optionsJSON[]Array de { value, label, disabled? }
valuestringValor seleccionado
placeholderstringTexto cuando no hay selección
disabledbooleanfalseDeshabilita el select
namestringNombre para formularios

Label sl-label

Etiqueta semántica para campos de formulario. Añade indicador visual de campo requerido.

Nombre de usuario
Email *
<sl-label for="mi-input" required>Email *</sl-label> <sl-input id="mi-input" type="email" required></sl-input>
AtributoTipoPor defectoDescripción
forstringID del campo asociado
requiredbooleanfalseMuestra indicador de obligatorio

Checkbox sl-checkbox

Casilla de selección booleana con etiqueta integrada.

Términos: sin marcar

<sl-checkbox label="Acepto los términos" name="terms"></sl-checkbox> <script> document.querySelector('sl-checkbox').addEventListener('change', (e) => { console.log(e.detail.checked) // boolean }) </script>
AtributoTipoPor defectoDescripción
labelstringTexto de la etiqueta
checkedbooleanfalseEstado marcado
disabledbooleanfalseDeshabilita el checkbox
valuestringValor para formularios
namestringNombre para formularios

Switch sl-switch

Interruptor de activación/desactivación. Alternativa visual a checkbox para preferencias.

Tamaños SM MD LG
Estados Off On Dis. off Dis. on

MD switch: on

<sl-switch size="md" name="notifications"></sl-switch> <script> document.querySelector('sl-switch').addEventListener('change', (e) => { console.log(e.detail.checked) // boolean }) </script>
AtributoTipoPor defectoDescripción
sizestringmdsm · md · lg
checkedbooleanfalseEstado activo
disabledbooleanfalseDeshabilita el switch
namestringNombre para formularios

Badge sl-badge

Etiqueta visual compacta para estados, categorías o contadores.

Variantes Default Secondary Success Error Warning Info Outline
Tamaños Pequeño Mediano Grande
<sl-badge variant="success">Activo</sl-badge> <sl-badge variant="info" size="sm">3</sl-badge>
AtributoTipoPor defectoDescripción
variantstringdefaultdefault · secondary · success · error · warning · info · outline
sizestringmdsm · md · lg

Avatar sl-avatar

Representación visual de un usuario. Muestra imagen cuando está disponible, cae en fallback con iniciales si falla.

SM sm
MD md
LG lg
XL xl
Con imagen AB CD EF (el tercero tiene URL rota → muestra fallback)
<sl-avatar size="md"> <sl-avatar-image src="/foto.jpg" alt="Nombre"></sl-avatar-image> <sl-avatar-fallback>NM</sl-avatar-fallback> </sl-avatar>
ElementoAtributoDescripción
sl-avatarsizesm · md · lg · xl
sl-avatar-imagesrcURL de la imagen. Si falla carga, muestra el fallback.
sl-avatar-imagealtTexto alternativo accesible
sl-avatar-fallback(slot)Contenido mostrado si la imagen no carga. Generalmente 1–2 iniciales.

Card sl-card

Contenedor de superficie con bordes y padding. Soporta slots para estructura compleja.

Card básica con contenido en el slot por defecto.

Con cabecera y shadow

Slot header + atributo shadow.

Demo
Con media

Slot media + padding="none"

Card completa

Todos los slots disponibles.

Compartir Editar
Destacado
<sl-card shadow> <div slot="header">Título</div> <img slot="media" src="..." alt="..."> <p>Contenido principal</p> <div slot="actions"> <sl-button size="sm">Acción</sl-button> </div> <div slot="footer"> <sl-badge>Etiqueta</sl-badge> </div> </sl-card>
NombreTipoDescripción
shadowatributoAñade sombra elevada
paddingatributonone · sm · md (por defecto)
headerslotZona de cabecera con borde inferior
mediaslotImagen o contenido visual al inicio
(default)slotContenido principal
actionsslotBotones de acción alineados a la derecha
footerslotZona de pie con borde superior

Icon sl-icon

Contenedor de iconos SVG inline con tamaños normalizados y semántica de accesibilidad correcta.

xs
sm
md
lg
xl
custom 3rem
Colores
<!-- Con label = accesible (role="img") --> <sl-icon size="md" label="Cerrar"> <svg viewBox="0 0 24 24" fill="currentColor">...</svg> </sl-icon> <!-- Sin label = decorativo (aria-hidden="true") --> <sl-icon size="md"> <svg viewBox="0 0 24 24" fill="currentColor">...</svg> </sl-icon> <!-- Tamaño personalizado --> <sl-icon style="--sl-icon-size: 3rem">...</sl-icon>
AtributoTipoPor defectoDescripción
sizestringmdxs · sm · md · lg · xl
labelstringDescripción accesible. Si no se especifica, el icono se oculta a lectores de pantalla.
--sl-icon-sizeCSS propAnula el tamaño predefinido con cualquier valor CSS

Tabs sl-tabs sl-tab sl-tab-content

Sistema de pestañas compuesto por tres elementos coordinados. Las pestañas y el contenido se sincronizan por nombre.

Cuenta Seguridad Notificaciones 3

Configuración de cuenta: nombre, email, foto de perfil.

Contraseña, autenticación en dos pasos, sesiones activas.

Tienes 3 notificaciones sin leer.

<sl-tabs> <sl-tab name="a" active>Primera</sl-tab> <sl-tab name="b">Segunda</sl-tab> </sl-tabs> <sl-tab-content name="a" active>Contenido A</sl-tab-content> <sl-tab-content name="b">Contenido B</sl-tab-content> <script> document.querySelector('sl-tabs').addEventListener('sl-tab-change', (e) => { console.log(e.detail.tab) // nombre de la pestaña activa }) </script>
ElementoAtributoDescripción
sl-tabnameIdentificador único de la pestaña
sl-tabactiveMarca la pestaña como activa por defecto
sl-tabdisabledDeshabilita la pestaña
sl-tab-contentnameDebe coincidir con el name del tab
sl-tab-contentactiveMuestra el contenido por defecto

Step Indicator sl-step-indicator

Indicador de progreso de pasos para flujos multi-etapa (wizard). Soporta variante horizontal y vertical.

← Anterior Siguiente →
<sl-step-indicator steps='[ { "label": "Cuenta" }, { "label": "Personal" }, { "label": "Revisión" }, { "label": "Listo" } ]' current="0" variant="horizontal" ></sl-step-indicator> <script> document.querySelector('sl-step-indicator').addEventListener('step-click', (e) => { console.log(e.detail.index) // índice del paso clicado }) </script>
AtributoTipoPor defectoDescripción
stepsJSON[]Array de { label: string, description?: string }
currentnumber0Índice del paso activo (base 0). Los anteriores se marcan como completados.
variantstringhorizontalhorizontal · vertical

Topbar sl-topbar

Barra de navegación superior. Soporta tres variantes: fija (pinned), flotante con márgenes (floating), o inline sin posición fija (flat).

Variantes Pinned Floating Flat
Logo
<!-- Topbar fija (default) --> <sl-topbar variant="pinned"> <a slot="start" href="/">Logo</a> <nav slot="center">...</nav> <div slot="end">Acciones</div> </sl-topbar> <!-- Topbar flotante --> <sl-topbar variant="floating">...</sl-topbar> <!-- Topbar inline --> <sl-topbar variant="flat">...</sl-topbar>
AtributoTipoPor defectoDescripción
variantstringpinnedpinned · floating · flat
heightstring3.5remAltura de la topbar

Dialog sl-dialog

Modal accesible construido sobre el elemento nativo <dialog>. Se abre y cierra con métodos JS nativos.

Dialog SM Dialog MD Dialog LG Confirmar borrado

Acción rápida

Este es un dialog pequeño para acciones simples.

Cerrar

Editar perfil

Nombre
Email
Cancelar Guardar

Términos y condiciones

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus lacinia odio vitae vestibulum vestibulum. Donec in efficitur leo, in commodo orci. Morbi commodo dui vel risus dignissim, vel commodo erat maximus.

Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper.

Rechazar Aceptar

¿Eliminar elemento?

Esta acción no se puede deshacer. El elemento será eliminado permanentemente.

Cancelar Eliminar
<sl-button onclick="document.getElementById('mi-dialog').showModal()">Abrir</sl-button> <sl-dialog id="mi-dialog" size="md"> <h2 slot="title">Título del dialog</h2> <p>Contenido del dialog.</p> <div slot="footer"> <sl-button variant="ghost" onclick="this.closest('sl-dialog').close()">Cancelar</sl-button> <sl-button onclick="this.closest('sl-dialog').close()">Confirmar</sl-button> </div> </sl-dialog>
NombreTipoDescripción
sizeatributosm · md · lg
titleslotCabecera del dialog con botón de cierre
(default)slotContenido del body
footerslotPie del dialog, típicamente botones de acción
showModal()métodoAbre el dialog (nativo)
close()métodoCierra el dialog (nativo)

Tooltip sl-tooltip

Globo informativo que aparece al pasar el cursor. Se posiciona automáticamente alrededor del trigger.

Arriba Abajo Izquierda Derecha Con retardo
<sl-tooltip content="Más información" placement="top"> <sl-button variant="outline">Hover</sl-button> </sl-tooltip>
AtributoTipoPor defectoDescripción
contentstringTexto del tooltip
placementstringtoptop · bottom · left · right
delaynumber200Retardo de aparición en ms

Popover sl-popover

Panel flotante de contenido libre anclado a un trigger. A diferencia del tooltip, puede contener cualquier HTML.

Abajo Título del popover

Clic fuera para cerrar.

Arriba

Popover anclado arriba.

Derecha

Popover anclado a la derecha.

<sl-popover placement="bottom"> <sl-popover-trigger> <sl-button>Abrir</sl-button> </sl-popover-trigger> <sl-popover-content> <p>Cualquier contenido HTML aquí.</p> </sl-popover-content> </sl-popover>
Atributo (en sl-popover)TipoPor defectoDescripción
placementstringbottomtop · bottom · left · right

Toast sl-toast

Notificaciones temporales imperativas. Se invocan con la función showToast(), no con HTML declarativo.

Default Success Error Warning Info Dismissible
import { showToast } from '@federa/solanda-ui/sl-toast' // Toast básico showToast({ message: '¡Guardado correctamente!' }) // Con opciones showToast({ message: 'El archivo se ha procesado.', variant: 'success', // 'default' | 'success' | 'error' | 'warning' | 'info' duration: 4000, // ms. 0 = no se cierra automáticamente dismissible: false // muestra botón de cerrar }) // Toast persistente con dismiss showToast({ message: 'Acción requerida.', variant: 'warning', duration: 0, dismissible: true })
OpciónTipoPor defectoDescripción
messagestringTexto del toast (requerido)
variantstringdefaultdefault · success · error · warning · info
durationnumber3000Duración en ms. 0 = permanente hasta dismiss.
dismissiblebooleanfalseMuestra botón de cierre manual

Alert sl-alert

Mensaje contextual con variantes visuales. Soporta cierre programático y slots para contenido.

Actualización disponible. Recarga la página para aplicar cambios. Los cambios se han guardado correctamente. La sesión expirará en 5 minutos. No se pudo conectar con el servidor. Alert sin título, estilo neutral.
<sl-alert variant="success" title="Guardado" dismissible> Los cambios se han guardado. </sl-alert> <!-- Cerrar programáticamente --> <script> document.querySelector('sl-alert').addEventListener('dismiss', (e) => { console.log('Alert cerrado') }) </script>
AtributoTipoPor defectoDescripción
variantstringdefaultdefault · info · success · warning · error
dismissiblebooleanfalseMuestra botón de cierre
titlestringTítulo opcional del alert

Spinner sl-spinner

Indicador de carga animado con tamaños predefinidos. Accesible vía role="status" y aria-label.

sm
md
lg
xl
<sl-spinner size="md"></sl-spinner> <sl-spinner size="sm" label="Cargando..."></sl-spinner>
AtributoTipoPor defectoDescripción
sizestringmdsm · md · lg · xl
labelstringLoadingTexto accesible (aria-label)

Skeleton sl-skeleton

Placeholder animado para contenido en carga. Variantes de forma y dimensiones personalizables.

<sl-skeleton variant="text"></sl-skeleton> <sl-skeleton variant="rectangle" width="200px" height="100px"></sl-skeleton> <sl-skeleton variant="circle" width="48px" height="48px"></sl-skeleton>
AtributoTipoPor defectoDescripción
variantstringtexttext · circle · rectangle · avatar
widthstringAncho CSS (ej: 100px, 50%)
heightstringAlto CSS (ej: 1rem, 20px)

Pagination sl-pagination

Navegación de páginas con soporte para elipsis, tamaños y eventos de cambio.

Tamaños

Página actual: 3

<sl-pagination total="20" current="5" size="md"></sl-pagination> <script> document.querySelector('sl-pagination').addEventListener('sl-pagination-change', (e) => { console.log('Página:', e.detail.page) }) </script>
AtributoTipoPor defectoDescripción
totalnumber1Número total de páginas
currentnumber1Página activa actual
sizestringmdsm · md · lg
show-ellipsisbooleantrueMuestra elipsis cuando hay muchas páginas
sibling-countnumber1Páginas visibles a cada lado de la actual

Accordion sl-accordion sl-accordion-item

Secciones colapsables usando <details>/<summary> nativos. Soporta modo exclusivo y flush.

¿Qué es SolandaUI?

Sistema de componentes web sin dependencias, construido con TypeScript y Shadow DOM.

¿Cómo empezar?

Importa sl-accordion desde npm o CDN y úsalo como HTML nativo.

Panel deshabilitado

Este panel no se puede abrir.

Variante flush: Sin bordes externos

Perfecto para integrar en cards o paneles.

Modo múltiple

Con multiple puedes abrir varios paneles simultáneamente.

<sl-accordion> <sl-accordion-item open> <span slot="title">Título</span> <p>Contenido colapsable.</p> </sl-accordion-item> </sl-accordion>
ElementoAtributoDescripción
sl-accordionmultiplePermite abrir varios ítems a la vez
sl-accordionflushnone · start · end · full
sl-accordion-itemopenÍtem abierto inicialmente
sl-accordion-itemdisabledDeshabilita el ítem

List Group sl-list-group sl-list-group-item

Lista flexible con variantes visuales, items activos/deshabilitados y modo horizontal.

Vertical con active Inbox Sent Drafts Archived
Horizontal Home Products About
<sl-list-group> <sl-list-group-item active>Activo</sl-list-group-item> <sl-list-group-item>Normal</sl-list-group-item> <sl-list-group-item disabled>Deshabilitado</sl-list-group-item> </sl-list-group>
ElementoAtributoDescripción
sl-list-groupvariantdefault · flush · horizontal
sl-list-groupsizesm · md · lg
sl-list-groupclickableHace los items clickables con selección automática
sl-list-group-itemactiveMarca el ítem como activo
sl-list-group-itemdisabledDeshabilita el ítem
sl-list-group-itemhrefConvierte el ítem en un enlace

Input Group sl-input-group sl-input-group-addon

Agrupa inputs con texto, iconos o botones a los lados.

@ Subscribe https:// /login
<sl-input-group> <span slot="prepend">$</span> <sl-input placeholder="Amount"></sl-input> </sl-input-group>
ElementoAtributo/SlotDescripción
sl-input-groupsizesm · md · lg
sl-input-grouphas-validationActiva borde de focus para validación
sl-input-groupslot="prepend"Contenido al inicio del grupo
sl-input-groupslot="append"Contenido al final del grupo
sl-input-group-addontextTexto del addon (alternativa al slot)

Offcanvas sl-offcanvas

Panel deslizante desde cualquier borde con backdrop, focus trap y keyboard dismiss.

← Start End → ↑ Top ↓ Bottom
Menú lateral

Panel desde la izquierda.

Cerrar
Notificaciones

Panel desde la derecha.

Cerrar
Aviso importante

Panel desde arriba.

Cerrar
Confirmar

Panel desde abajo.

Cancelar Confirmar
<sl-offcanvas id="menu" placement="start" size="md" backdrop> <span slot="title">Título</span> <p>Contenido...</p> </sl-offcanvas> <script> const offcanvas = document.getElementById('menu') offcanvas.show() // Mostrar offcanvas.hide() // Ocultar offcanvas.toggle() // Alternar </script>
AtributoTipoPor defectoDescripción
placementstringendstart · end · top · bottom
sizestringmdsm · md · lg · full
closablebooleantruePermite cerrar con Escape, botón o backdrop
backdropbooleanfalseMuestra overlay semitransparente
EventoDescripción
sl-offcanvas-openSe dispara cuando el offcanvas se abre
sl-offcanvas-closeSe dispara cuando el offcanvas se cierra

Section Header sl-section-header

Cabecera de sección con eyebrow, título y descripción. Componente de composición para landing pages y documentación.

Lo que construimos

Una descripción opcional que contextualiza la sección.

<sl-section-header eyebrow="Overview"> <span slot="title">Section Title</span> <p>Description text goes here.</p> </sl-section-header>
NombreTipoDescripción
eyebrowatributoTexto pequeño sobre el título
titleslotTítulo de la sección
(default)slotDescripción o contenido adicional

Feature Card sl-feature-card

Tarjeta promocional para listar características con icono, título y descripción.

Construido para rendimiento con bundle mínimo.

ARIA attributes y navegación por teclado incluidos.

<sl-feature-card title="Lightning Fast"> <sl-icon slot="icon" size="lg">⚡</sl-icon> <p>Optimized for performance.</p> </sl-feature-card>
NombreTipoDescripción
titleatributoTítulo de la feature card
iconslotIcono visible en la parte superior
(default)slotDescripción o contenido

Showcase Card sl-showcase-card

Contenedor tipo ventana con barra de título (estilo macOS) para mostrar demos y previsualizaciones.

Contenido de ejemplo dentro del showcase card.

<sl-showcase-card title="Preview"> <p>Demo content here.</p> </sl-showcase-card>
NombreTipoDescripción
titleatributoTítulo mostrado en la barra del encabezado
(default)slotContenido del cuerpo del showcase

Doc Block sl-doc-block

Bloque de contenido para páginas de documentación con título y área de contenido.

Este es el contenido dentro del doc-block.

<sl-doc-block title="Installation"> <p>Install with npm:</p> <code>npm install @federa/solanda-ui</code> </sl-doc-block>
AtributoTipoPor defectoDescripción
titlestring''Título del bloque documental
(default)slotContenido del bloque