JavaScript API

13 módulos Vanilla JS — todos como IIFE, sin dependencias, cada uno con una API window.WB*. Incluidos con una sola etiqueta <script>.

Resumen de módulos

Módulowindow.*Métodos principales
theme.jsWBThemesetMode, setAccent, setPreset, setRadius, setDensity
modal.jsWBModalopen(id), close(id)
drawer.jsWBDraweropen(id), close(id)
dropdown.jsWBDropdownopen(el), close(el)
tabs.jsWBTabsactivate(tabEl)
accordion.jsWBAccordionopen(itemEl), close(itemEl)
sidebar.jsWBSidebaropen(), close()
nav-group.jsWBNavGroupopen(groupEl), close(groupEl), init()
toast.jsWBToastshow(msg, opts), dismiss(toastEl)
popover.jsWBPopoveropen(wrapperEl), close(wrapperEl), closeAll()
tooltip.jsWBTooltipshow(el), hide(el), hideAll()
dismiss.jsWBDismissdismiss(el)
command-palette.jsWBCommandPaletteopen(id), close(id), register(id, opts)
ajax-toggle.jsWBAjaxTogglehandle(checkboxEl) — automático via evento change

WBTheme

theme.js

Gestiona todos los ejes del tema — establece atributos data-* en <html> y persiste los valores en localStorage.

WBTheme.setMode(value: 'light' | 'dark' | 'auto')
WBTheme.setAccent(value: string)
WBTheme.setPreset(value: string)
WBTheme.setRadius(value: 'sharp' | 'soft')
WBTheme.setDensity(value: 'compact' | 'comfortable')
// Activar modo oscuro
WBTheme.setMode('dark');

// Cambiar color de acento
WBTheme.setAccent('forest');

// Aplicar preset (agrupa radius/shadow/density/font/border)
WBTheme.setPreset('rounded');

// Ajuste fino de ejes individuales
WBTheme.setRadius('sharp');
WBTheme.setDensity('compact');

Disparadores por atributo data (sin JS)

<!-- Ciclo: light → dark → auto -->
<button data-wb-mode-cycle>Cambiar modo</button>

<!-- Establecer modo específico -->
<button data-wb-mode-set="dark">Oscuro</button>
<button data-wb-mode-set="light">Claro</button>
<button data-wb-mode-set="auto">Auto</button>

<!-- Establecer color de acento -->
<button data-wb-accent-set="ocean">Ocean</button>
<button data-wb-accent-set="forest">Forest</button>
Claves de localStorage: wb-mode, wb-accent, wb-preset, wb-radius, wb-density. Los valores se restauran automáticamente al cargar la página. Para restablecerlos, elimina estas claves.

WBModal

modal.js

Abre y cierra overlays de diálogo. Gestiona los estados is-open/is-leaving, bloqueo del scroll, tecla Escape y clic en el fondo.

WBModal.open(id: string)
WBModal.close(id: string)
WBModal.open('my-modal');
WBModal.close('my-modal');

Disparadores por atributo data

<!-- Abrir -->
<button data-wb-toggle="modal" data-wb-target="#my-modal">Abrir</button>

<!-- Cerrar (dentro del modal) -->
<button data-wb-dismiss="modal">Cerrar</button>
<div class="wb-modal-backdrop" data-wb-dismiss="modal"></div>

Diálogo de confirmación (wb-confirm)

<div class="wb-modal wb-confirm" id="confirm-delete">
  <div class="wb-modal-backdrop" data-wb-dismiss="modal"></div>
  <div class="wb-modal-dialog">
    <div class="wb-confirm-icon wb-confirm-danger">!</div>
    <h4 class="wb-confirm-title">¿Eliminar registro?</h4>
    <p class="wb-confirm-desc">Esta acción no se puede deshacer.</p>
    <div class="wb-confirm-actions">
      <button class="wb-btn wb-btn-ghost" data-wb-dismiss="modal">Cancelar</button>
      <button class="wb-btn wb-btn-danger" id="confirm-btn">Eliminar</button>
    </div>
  </div>
</div>

WBDrawer

drawer.js

Panel lateral deslizante con trampa de foco completa. Teclado: Escape cierra; Tab cicla dentro del panel.

WBDrawer.open(id: string)
WBDrawer.close(id: string)
WBDrawer.open('my-drawer');
WBDrawer.close('my-drawer');

Disparadores por atributo data

<button data-wb-toggle="drawer" data-wb-target="#my-drawer">Abrir</button>
<button data-wb-dismiss="drawer">Cerrar</button>

WBDropdown

dropdown.js

Alterna is-open en un wrapper wb-dropdown. Cierra al hacer clic fuera y con Escape.

WBDropdown.open(wrapperEl: Element)
WBDropdown.close(wrapperEl: Element)
var wrapper = document.querySelector('.wb-dropdown');
WBDropdown.open(wrapper);
WBDropdown.close(wrapper);

Disparadores por atributo data

<div class="wb-dropdown">
  <button data-wb-toggle="dropdown">Abrir menú</button>
  <div class="wb-dropdown-menu">...</div>
</div>

WBTabs

tabs.js

Activa elementos de pestaña y sus paneles correspondientes.

WBTabs.activate(tabEl: Element)
var tab = document.querySelector('[data-wb-tab="tab2"]');
WBTabs.activate(tab);

Estructura HTML

<div class="wb-tabs">
  <div class="wb-tab-list">
    <button class="wb-tab-item is-active" data-wb-tab="panel1">Tab 1</button>
    <button class="wb-tab-item"            data-wb-tab="panel2">Tab 2</button>
  </div>
  <div class="wb-tab-panels">
    <div class="wb-tab-panel is-active" id="panel1">Contenido 1</div>
    <div class="wb-tab-panel"           id="panel2">Contenido 2</div>
  </div>
</div>

WBAccordion

accordion.js

Alterna is-open en elementos de acordeón. Los clics en wb-accordion-trigger se conectan automáticamente.

WBAccordion.open(itemEl: Element)
WBAccordion.close(itemEl: Element)
var item = document.querySelector('.wb-accordion-item');
WBAccordion.open(item);
WBAccordion.close(item);

WBSidebar

sidebar.js

Abre y cierra el overlay de sidebar móvil. Añade/elimina is-open en .wb-sidebar y .wb-dashboard-shell.

WBSidebar.open()
WBSidebar.close()
WBSidebar.open();
WBSidebar.close();

Disparadores por atributo data

<button data-wb-toggle="sidebar">☰ Menú</button>

WBNavGroup

nav-group.js

Grupos de navegación expandibles en la sidebar. Soporta modo acordeón opcional.

WBNavGroup.open(groupEl: Element)
WBNavGroup.close(groupEl: Element)
WBNavGroup.init() Llamar tras cambios dinámicos en el DOM
<!-- Grupo simple -->
<div class="wb-nav-group">
  <button class="wb-nav-group-trigger">
    Usuarios
    <svg class="wb-nav-group-chevron" width="12" height="12" viewBox="0 0 24 24"
         fill="none" stroke="currentColor" stroke-width="2">
      <path d="m6 9 6 6 6-6"/>
    </svg>
  </button>
  <div class="wb-nav-group-body">
    <a href="#" class="wb-sidebar-link">Todos los usuarios</a>
    <a href="#" class="wb-sidebar-link">Roles</a>
  </div>
</div>

<!-- Modo acordeón: cierra otros grupos al abrir uno nuevo -->
<nav class="wb-sidebar-nav" data-wb-nav-group-accordion>
  <!-- nav groups here -->
</nav>

WBToast

toast.js

Muestra notificaciones toast de forma programática. Crea el contenedor automáticamente en la primera llamada.

WBToast.show(message: string, options?: object) → Element
WBToast.dismiss(toastEl: Element)

Opciones

OpciónTipoPredeterminadoDescripción
typestring'default''default' · 'success' · 'error' · 'warning' · 'info'
durationnumber4000Retraso antes del cierre automático en ms. 0 = desactivado.
positionstring'top-right''top-right' · 'top-center' · 'top-left' · 'bottom-center' · 'bottom-left'
dismissiblebooleantrueMostrar botón de cierre en el toast
// Simple
WBToast.show('Configuración guardada.');

// Con tipo
WBToast.show('¡Registro eliminado!', { type: 'success' });
WBToast.show('Error al subir.', { type: 'error' });

// Duración personalizada + posición
WBToast.show('Procesando…', {
  type: 'info',
  duration: 0,          // permanece hasta cerrar manualmente
  position: 'bottom-center'
});

// Cierre programático
var toast = WBToast.show('Mensaje largo');
WBToast.dismiss(toast);

WBPopover

popover.js

Alterna is-open en un wb-popover-wrapper. Cierra al hacer clic fuera y con Escape.

WBPopover.open(wrapperEl: Element)
WBPopover.close(wrapperEl: Element)
WBPopover.closeAll()
<div class="wb-popover-wrapper">
  <button data-wb-toggle="popover">Clic aquí</button>
  <div class="wb-popover wb-popover-top">
    <div class="wb-popover-title">Título</div>
    <div class="wb-popover-body">Contenido aquí.</div>
  </div>
</div>

<!-- Posiciones: wb-popover-top / -right / -bottom / -left -->

WBTooltip

tooltip.js

Muestra/oculta tooltips definidos via data-wb-tooltip. Se activa al pasar el cursor y al enfocar. Retraso de aparición predeterminado: 300ms.

WBTooltip.show(el: Element)
WBTooltip.hide(el: Element)
WBTooltip.hideAll()
<!-- HTML -->
<button data-wb-tooltip="Haz clic para guardar"
        data-wb-tooltip-placement="top">
  Guardar
</button>

<!-- Posiciones: top (predeterminado) / right / bottom / left -->

<!-- JS -->
var el = document.querySelector('[data-wb-tooltip]');
WBTooltip.show(el);
WBTooltip.hide(el);

WBDismiss

dismiss.js

Oculta alertas y banners con una animación is-leaving antes de eliminarlos.

WBDismiss.dismiss(el: Element)
<!-- HTML -->
<div class="wb-alert wb-alert-info" id="my-alert">
  Texto del mensaje.
  <button data-wb-dismiss="alert" class="wb-alert-close">&times;</button>
</div>

<!-- JS -->
WBDismiss.dismiss(document.getElementById('my-alert'));

El atributo data-wb-dismiss="alert" conecta el cierre automáticamente. El uso programático es para casos en que se necesita cerrar desde código externo.

WBCommandPalette

command-palette.js

Overlay de paleta de comandos en pantalla completa con navegación por teclado. Se abre con Cmd+K / Ctrl+K.

WBCommandPalette.register(id: string, options?: object)
WBCommandPalette.open(id: string)
WBCommandPalette.close(id: string)

Opciones

OpciónTipoDescripción
onSearchfunction(query, results)Se llama en cada pulsación de tecla. Recibe el término de búsqueda y una NodeList filtrada de resultados.
// Registro simple (búsqueda de texto integrada)
WBCommandPalette.register('#my-cmd');

// Con manejador de búsqueda personalizado
WBCommandPalette.register('#my-cmd', {
  onSearch: function(query, results) {
    // results es una NodeList de elementos .wb-cmd-result que coinciden con la búsqueda
    console.log(query, results.length + ' resultados');
  }
});

// Abrir/cerrar programáticamente
WBCommandPalette.open('#my-cmd');
WBCommandPalette.close('#my-cmd');

Atajos de teclado

TeclaAcción
Cmd/Ctrl+KAbrir la primera paleta registrada
↑ / ↓Navegar por los resultados
EnterActivar el resultado seleccionado
EscapeCerrar la paleta

WBAjaxToggle

ajax-toggle.js

Envía una petición AJAX POST cuando una checkbox cambia de estado. Lee el token CSRF del tag meta[name=csrf-token]. Revierte en caso de error y muestra un toast.

WBAjaxToggle.handle(checkboxEl: Element) Llamado automáticamente via evento change

Atributos data

AtributoRequeridoDescripción
data-wb-ajax-toggleMarca la checkbox para comportamiento AJAX toggle
data-wb-urlURL POST para la petición de toggle
data-wb-fieldNoNombre del campo JSON a enviar ({ field: checked }). Predeterminado: value
data-wb-successNoMensaje toast en caso de éxito
data-wb-errorNoMensaje toast en caso de error (predeterminado: 'Error occurred')
<!-- HTML -->
<input
  type="checkbox"
  class="wb-switch"
  data-wb-ajax-toggle
  data-wb-url="/api/users/42/toggle-active"
  data-wb-field="is_active"
  data-wb-success="Estado actualizado"
  data-wb-error="No se pudo actualizar el estado"
  checked
>

<!-- Ejemplo con Laravel Blade -->
<input
  type="checkbox"
  class="wb-switch"
  data-wb-ajax-toggle
  data-wb-url="{{ route('users.toggle', $user) }}"
  data-wb-field="is_active"
  data-wb-success="Estado actualizado"
  {{ $user->is_active ? 'checked' : '' }}
>

<!-- Meta tag CSRF (requerido en <head>) -->
<meta name="csrf-token" content="{{ csrf_token() }}">

Formato de la petición

// POST a data-wb-url
// Headers: Content-Type: application/json, X-CSRF-TOKEN: ...
// Body:    { "is_active": true }

// En éxito: mostrar WBToast(data-wb-success, { type: 'success' })
// En error: revertir estado de checkbox + WBToast(data-wb-error, { type: 'error' })

Convenciones JS

Patrones comunes usados en todos los módulos.

Clases de estado

ClaseUso
is-openEl elemento está visible/activo (Modal, Drawer, Dropdown, Sidebar)
is-activeEstado seleccionado (Tabs, Nav-Links, Filter-Chips)
is-selectedEstado de selección (filas de tabla, elementos de lista)
is-leavingAnimación de cierre en curso — se añade antes de eliminar is-open

Patrón de animación is-leaving

Todas las animaciones de cierre siguen esta secuencia para evitar desapariciones abruptas:

// 1. Añadir is-leaving (activa la transición CSS de cierre)
element.classList.add('is-leaving');

// 2. Esperar a transitionend (con fallback de 300ms)
element.addEventListener('transitionend', function handler() {
  element.classList.remove('is-open', 'is-leaving');
  element.removeEventListener('transitionend', handler);
}, { once: true });

// Fallback si transitionend no se dispara
setTimeout(function() {
  element.classList.remove('is-open', 'is-leaving');
}, 300);

Conexión universal por atributo data

<!-- Abrir cualquier componente togglable -->
<button data-wb-toggle="modal|drawer|dropdown|sidebar|cmd"
        data-wb-target="#target-id">Abrir</button>

<!-- Cerrar desde dentro -->
<button data-wb-dismiss="modal|drawer|alert">Cerrar</button>
Patrón de módulo: Todos los módulos usan IIFE — (function(){ 'use strict'; … })() — y exponen su API en window. No hay contaminación del espacio de nombres global; cada módulo es completamente autónomo.