Biblioteca de componentes

16 patrones congelados + 18 · Movimiento · Centro Deportivo Aurora · datos dummy de un centro deportivo chileno

Índice de patrones

click para saltar

1 · Tabla de datos con paginación

patrón 1 / 16

Lista de planes de los alumnos. Filtros en la cabecera, fila densa de 36 px, acciones a la derecha y paginación en .table-foot.

Alumnos y sus planes

Alumno Plan Inicio Término Estado Cupos Acciones
CFCamila Fuentes Rojas Full Mensual 01-09-2026 30-09-2026 Activo 18 / 30 Perfil
TATomás Aguirre Lillo 12 Sesiones 14-08-2026 14-09-2026 Por vencer 3 / 12 Perfil
JCJosefa Cáceres Núñez Full Trimestral 02-07-2026 02-10-2026 Activo 61 / 90 Perfil
DSDiego Salinas Ortiz Estudiante 10-08-2026 10-09-2026 Vencido 0 / 12 Perfil
Mostrando 1–20 de 412 alumnos

HTML para copiar:

Ver el HTML para copiar
<div class="card">
  <div class="card-head">
    <h3 class="card-title">Alumnos y sus planes</h3>
    <div class="card-tools">
      <div class="field field-search field-search-inline">
        <i data-lucide="search" class="nav-ico size-3"></i>
        <input type="search" placeholder="Buscar alumno o plan…" aria-label="Buscar alumno o plan">
      </div>
      <select class="field" aria-label="Estado del plan"><option selected>Todos los estados</option></select>
    </div>
  </div>
  <div class="table-wrap">
    <table class="table-dense">
      <thead>
        <tr>
          <th><span class="th-sort is-desc">Alumno<i data-lucide="chevron-down" class="nav-ico"></i></span></th>
          <th>Plan</th><th>Inicio</th><th>Término</th><th>Estado</th>
          <th class="td-num">Cupos</th><th class="td-actions">Acciones</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td><span class="cell-strong"><span class="ava">CF</span>Camila Fuentes Rojas</span></td>
          <td class="td-main">Full Mensual</td>
          <td><span class="mono text-mini text-text-muted">01-09-2026</span></td>
          <td><span class="mono text-mini text-text-muted">30-09-2026</span></td>
          <td><span class="badge badge-mint">Activo</span></td>
          <td class="td-num">18 / 30</td>
          <td class="td-actions"><span class="row-actions">
            <a class="link-action" href="#">Perfil<i data-lucide="arrow-up-right" class="nav-ico size-3"></i></a>
            <a class="btn btn-xs btn-ghost btn-icon" href="tel:+56984127735" title="Llamar"><i data-lucide="phone" class="nav-ico size-3"></i></a>
          </span></td>
        </tr>
      </tbody>
    </table>
  </div>
  <div class="table-foot">
    <span class="pager-info">Mostrando <strong>1–20</strong> de <strong>412</strong> alumnos</span>
    <nav class="pager" aria-label="Paginación">
      <button type="button" class="pager-btn" disabled aria-label="Anterior"><i data-lucide="chevron-left" class="nav-ico size-3"></i></button>
      <button type="button" class="pager-btn is-active" aria-current="page">1</button>
      <button type="button" class="pager-btn">2</button>
      <button type="button" class="pager-btn" aria-label="Siguiente"><i data-lucide="chevron-right" class="nav-ico size-3"></i></button>
    </nav>
    <span class="pager-size">
      <label class="text-mini text-text-muted" for="por-pagina">Por página</label>
      <select class="field" id="por-pagina"><option selected>20</option><option>50</option></select>
    </span>
  </div>
</div>

1.b · Estado CARGANDO

aria-busy="true"

Cinco filas de esqueleto, sin texto. Se marca con aria-busy="true" en el tbody.

AlumnoPlanVencimientoCupos

HTML para copiar:

Ver el HTML para copiar
<div class="card">
  <div class="table-wrap">
    <table class="table-dense">
      <thead><tr><th>Alumno</th><th>Plan</th><th>Vencimiento</th><th class="td-num">Cupos</th></tr></thead>
      <tbody aria-busy="true">
        <tr>
          <td><span class="cell-loading"><span class="skel-ava"></span><span class="skel skel-md"></span></span></td>
          <td><span class="skel skel-sm"></span></td>
          <td><span class="skel skel-md"></span></td>
          <td class="td-num"><span class="skel skel-xs"></span></td>
        </tr>
      </tbody>
    </table>
  </div>
</div>

1.c · Estado VACÍO (sin datos jamás)

colspan

0 registros y sin filtros aplicados: fila única con colspan + estado vacío del patrón 8 + acción primaria de alta.

Plantillas de WhatsApp

NombreCuerpo del mensajeActivoAcciones
Aún no hay plantillas creadas Crea la primera plantilla para responder por WhatsApp a los alumnos del centro.

HTML para copiar:

Ver el HTML para copiar
<div class="table-wrap">
  <table class="table-dense">
    <thead><tr><th>Nombre</th><th>Cuerpo del mensaje</th><th>Activo</th><th class="td-actions">Acciones</th></tr></thead>
    <tbody>
      <tr>
        <td class="table-state" colspan="4">
          <div class="empty">
            <i data-lucide="inbox" class="empty-ico"></i>
            <span class="empty-title">Aún no hay plantillas creadas</span>
            <span class="empty-text">Crea la primera plantilla para responder por WhatsApp a los alumnos del centro.</span>
            <span class="empty-action">
              <button type="button" class="btn btn-primary"><i data-lucide="plus" class="nav-ico size-3"></i>Nueva plantilla</button>
            </span>
          </div>
        </td>
      </tr>
    </tbody>
  </table>
</div>

1.d · Estado SIN RESULTADOS (filtro activo)

colspan

Hay datos, pero el filtro no devolvió filas: se nombra el término y se ofrece limpiar los filtros.

Alumnos inactivos

AlumnoÚltimo planFecha de términoClases restantes

HTML para copiar:

Ver el HTML para copiar
<tr>
  <td class="table-state" colspan="4">
    <div class="empty is-search">
      <i data-lucide="search-x" class="empty-ico"></i>
      <span class="empty-title">Sin resultados para «plan anual»</span>
      <span class="empty-text">Revisa el término o limpia los filtros para ver los 158 alumnos inactivos.</span>
      <span class="empty-action">
        <button type="button" class="btn btn-outline"><i data-lucide="rotate-ccw" class="nav-ico size-3"></i>Limpiar filtros</button>
      </span>
    </div>
  </td>
</tr>

1.e · Estado ERROR (falló la carga)

error de red

La carga falló: badge rojo + mensaje + botón outline para reintentar.

Registro de pagos y boletas

ServicioFecha BoletaTotalAcciones
No pudimos cargar los pagos Hubo un problema al consultar el registro. Vuelve a intentarlo en unos segundos. Error 500

HTML para copiar:

Ver el HTML para copiar
<tr>
  <td class="table-state" colspan="4">
    <div class="empty is-error">
      <i data-lucide="alert-circle" class="empty-ico"></i>
      <span class="empty-title">No pudimos cargar los pagos</span>
      <span class="empty-text">Hubo un problema al consultar el registro. Vuelve a intentarlo en unos segundos.</span>
      <span class="empty-action">
        <span class="badge badge-red">Error 500</span>
        <button type="button" class="btn btn-outline"><i data-lucide="refresh-cw" class="nav-ico size-3"></i>Reintentar</button>
      </span>
    </div>
  </td>
</tr>

2 · Formulario (label · ayuda · error · requerido · campo con icono)

patrón 2 / 16

Alta de alumno. Todos los estados visibles: requerido, ayuda, error, campo con icono, select, textarea, checkbox y switch.

Datos del alumno
Como aparecerá en la lista de alumnos y en la app.
Falta el dominio del correo (ej. @gmail.com).
Se usa para avisos por WhatsApp.
Formato dd-mm-aaaa.
$
El monto no puede ser $0 si el plan no es Prueba.
Preferencias

HTML para copiar:

Ver el HTML para copiar
<form class="form" action="#">
  <div class="form-section">
    <div class="form-section-title"><i data-lucide="user" class="nav-ico"></i>Datos del alumno</div>
    <div class="form-grid">
      <div class="field-wrap">
        <label class="field-label" for="f-nombre">Nombre completo<span class="field-req">*</span></label>
        <div class="field field-lg field-block"><input id="f-nombre" type="text" value="Valentina Ríos Peña" required></div>
        <span class="field-help">Como aparecerá en la lista de alumnos y en la app.</span>
      </div>
      <div class="field-wrap">
        <label class="field-label" for="f-correo">Correo electrónico<span class="field-req">*</span></label>
        <div class="field field-lg field-block"><input id="f-correo" type="email" value="v.rios" required></div>
        <span class="field-msg"><i data-lucide="alert-circle" class="nav-ico"></i>Falta el dominio del correo.</span>
      </div>
      <div class="field-wrap">
        <label class="field-label" for="f-fono">Teléfono</label>
        <div class="field field-lg field-block">
          <i data-lucide="phone" class="field-ico"></i>
          <input id="f-fono" type="tel" value="+56 9 6234 8811">
        </div>
        <span class="field-help">Se usa para avisos por WhatsApp.</span>
      </div>
      <div class="field-wrap">
        <label class="field-label" for="f-plan">Plan</label>
        <select class="field field-lg field-block" id="f-plan">
          <option>Full Mensual · $45.000</option>
          <option selected>Full Trimestral · $120.000</option>
        </select>
      </div>
      <div class="field-wrap form-col-full">
        <label class="field-label" for="f-obs">Observaciones</label>
        <div class="field field-lg field-textarea field-block"><textarea id="f-obs" rows="3"></textarea></div>
      </div>
    </div>
  </div>
  <div class="form-section">
    <label class="check" for="f-welcome">
      <input id="f-welcome" type="checkbox" checked>
      <span class="check-box"><i data-lucide="check" class="nav-ico"></i></span>
      <span class="check-text">
        <span>Enviar correo de bienvenida</span>
        <span class="check-help">Le llega el acceso a la app y el link de autorregistro.</span>
      </span>
    </label>
    <label class="switch" for="f-activo">
      <input id="f-activo" type="checkbox" checked>
      <span class="switch-track"></span>
      <span>Alumno activo</span>
    </label>
  </div>
  <div class="form-foot">
    <button type="button" class="btn btn-ghost form-foot-left"><i data-lucide="arrow-left" class="nav-ico size-3"></i>Volver</button>
    <button type="button" class="btn btn-outline">Cancelar</button>
    <button type="button" class="btn btn-primary"><i data-lucide="check" class="nav-ico size-3"></i>Agregar alumno</button>
  </div>
</form>

3 · Modal (confirmar, avisar, pedir un dato · ≤ 3 campos)

abierto como demo

Confirmación destructiva. En una página real el overlay se muestra con .is-open (lo alterna el runtime); aquí se agrega .is-static solo para poder verlo dentro del catálogo. El overlay completo usa .modal-overlay.is-open a pantalla completa.

HTML para copiar:

Ver el HTML para copiar
<div class="modal-overlay is-open">
  <div class="modal" role="dialog" aria-modal="true" aria-labelledby="modal-eliminar-titulo">
    <div class="modal-head">
      <span class="modal-icon is-danger"><i data-lucide="alert-triangle" class="nav-ico"></i></span>
      <div class="min-w-0 flex-1">
        <h3 class="modal-title" id="modal-eliminar-titulo">Eliminar alumno</h3>
        <p class="modal-desc">Esta acción no se puede deshacer.</p>
      </div>
      <button type="button" class="modal-x" aria-label="Cerrar"><i data-lucide="x" class="nav-ico size-3"></i></button>
    </div>
    <div class="modal-body">
      <p>¿Confirmas eliminar a <strong>Josefa Cáceres Núñez</strong>? Se borrarán su ficha, su plan <span class="mono">Full Trimestral</span> vigente y su historial de reservas.</p>
    </div>
    <div class="modal-foot">
      <button type="button" class="btn btn-ghost">Cancelar</button>
      <button type="button" class="btn btn-danger"><i data-lucide="trash-2" class="nav-ico size-3"></i>Eliminar alumno</button>
    </div>
  </div>
</div>
<!-- catálogo: agregar is-static al overlay para verlo embebido -->

4 · Drawer / panel lateral (formulario largo o detalle · > 3 campos)

abierto como demo

Editar un plan. Mismo criterio que el modal: .is-open en producción, .is-static para verlo aquí. Variantes: .drawer-left y .drawer-wide.

HTML para copiar:

Ver el HTML para copiar
<div class="drawer-overlay is-open"></div>
<div class="drawer is-open" role="dialog" aria-modal="true" aria-labelledby="drawer-plan-titulo">
  <div class="drawer-head">
    <div class="min-w-0 flex-1">
      <h3 class="drawer-title" id="drawer-plan-titulo">Editar plan Full Trimestral</h3>
      <p class="drawer-desc">Josefa Cáceres Núñez · vigente hasta el 02-10-2026</p>
    </div>
    <button type="button" class="drawer-x" aria-label="Cerrar"><i data-lucide="x" class="nav-ico size-3"></i></button>
  </div>
  <div class="drawer-body">
    <div class="form-section">
      <div class="form-grid">
        <div class="field-wrap">
          <label class="field-label" for="d-plan">Plan</label>
          <select class="field field-lg field-block" id="d-plan"><option selected>Full Trimestral · $120.000</option></select>
        </div>
        <div class="field-wrap">
          <label class="field-label" for="d-inicio">Inicio</label>
          <div class="field field-lg field-block"><input id="d-inicio" type="text" value="02-07-2026"></div>
        </div>
        <div class="field-wrap form-col-full">
          <label class="field-label" for="d-nota">Nota interna</label>
          <div class="field field-lg field-textarea field-block"><textarea id="d-nota" rows="2"></textarea></div>
        </div>
      </div>
    </div>
    <div class="form-section">
      <div class="bar-label"><span>Ocupación del plan</span><span class="bar-pct">68 %</span></div>
      <div class="bar bar-lg is-warn"><span style="width:68%"></span></div>
    </div>
  </div>
  <div class="drawer-foot">
    <button type="button" class="btn btn-ghost">Cancelar</button>
    <button type="button" class="btn btn-primary"><i data-lucide="check" class="nav-ico size-3"></i>Guardar cambios</button>
  </div>
</div>

5 · KPI / stat card

patrón 5 / 16

Fila compacta de 3 (o 4) y stat card aislada con tile de icono y tendencia.

Alumnos de septiembre

03 contadores
ACTIVOS 412 positivo
PRUEBA 37 advertencia
INACTIVOS 158 negativo
Ingresos del mes
$8.914.500 +12,4 % vs. agosto 2026
PLANES 163
CLASES 2.418
MATRÍCULAS 31
OCUPACIÓN 78 %

HTML para copiar:

Ver el HTML para copiar
<div class="card">
  <div class="card-head"><h3 class="card-title">Alumnos de septiembre</h3></div>
  <div class="kpi-row">
    <div class="kpi">
      <span class="kpi-label"><span class="dot bg-primary"></span>ACTIVOS</span>
      <span class="kpi-value">412</span>
      <span class="kpi-foot"><i data-lucide="trending-up" class="nav-ico size-3"></i>positivo</span>
    </div>
    <div class="kpi">
      <span class="kpi-label"><span class="dot bg-secondary"></span>PRUEBA</span>
      <span class="kpi-value">37</span>
      <span class="kpi-foot">advertencia</span>
    </div>
    <div class="kpi">
      <span class="kpi-label"><span class="dot bg-destructive"></span>INACTIVOS</span>
      <span class="kpi-value">158</span>
      <span class="kpi-foot">negativo</span>
    </div>
  </div>
</div>

<!-- stat card aislada -->
<div class="card">
  <div class="kpi-card">
    <div class="kpi-card-head">
      <span class="kpi-tile"><i data-lucide="dollar-sign" class="nav-ico"></i></span>
      <span class="kpi-label">Ingresos del mes</span>
    </div>
    <span class="kpi-value">$8.914.500</span>
    <span class="kpi-foot">
      <span class="kpi-trend is-up"><i data-lucide="trending-up" class="nav-ico size-3"></i>+12,4 %</span>
      vs. agosto 2026
    </span>
  </div>
</div>

6 · Badges de estado (todos los del diccionario)

patrón 6 / 16

Regla de color única: mint positivo · lima advertencia · rojo negativo/lleno · neutro sin estado · info asistió/integración. Siempre forma + color + texto.

Estado del alumno (users.status_user)
Activo Inactivo Prueba Sin estado
Estado del plan del alumno (plan_user.plan_status_id)
Activo Congelado Precompra Finalizado Cancelado Vencido
Estado de la reserva (reservations.reservation_status_id)
Pendiente Confirmada Consumida Perdida Eliminada
Estado de la clase y ocupación
Activa Cerrada Restringida Con cupo LLENO Cancelada
Pagos y documentos tributarios
Pagada Pendiente Finalizada Anulada Emisión fallida Aceptado Aceptado con Reparo Rechazado Sin emisión
Procedencia del alumno (con icono)
Instagram Página web Recomendación Presencial Wellhub NFIT Go

HTML para copiar:

Ver el HTML para copiar
<span class="badge badge-mint">Activo</span>
<span class="badge badge-red">Inactivo</span>
<span class="badge badge-lime">Prueba</span>
<span class="badge badge-neutral">Sin estado</span>
<span class="badge badge-info">Consumida</span>

<!-- badge con icono + punto -->
<span class="badge badge-mint"><i data-lucide="check" class="nav-ico size-3"></i>Confirmada</span>
<span class="badge badge-mint"><span class="badge-dot"></span>Con cupo</span>

7 · Avatares (iniciales de color)

patrón 7 / 16

Base 22 px · .ava-sm 18 px · .ava-lg 36 px · grupo con .ava-more. En tablas usar el avatar neutro.

CF MH JC VR TA DS AB CFMHJC+9 FEFernanda Espinoza Díaz

HTML para copiar:

Ver el HTML para copiar
<span class="ava">CF</span>
<span class="ava ava-sm">MH</span>
<span class="ava ava-lg">JC</span>
<span class="ava ava-mint">VR</span>
<span class="ava ava-lime">TA</span>
<span class="ava ava-red">DS</span>
<span class="ava ava-info">AB</span>

<!-- grupo -->
<span class="ava-group">
  <span class="ava">CF</span><span class="ava">MH</span><span class="ava">JC</span><span class="ava ava-more">+9</span>
</span>

<!-- nombre + avatar en una celda -->
<span class="cell-strong"><span class="ava">FE</span>Fernanda Espinoza Díaz</span>

8 · Estados vacíos con acción

patrón 8 / 16

Tres variantes: sin datos (.empty), sin resultados (.empty.is-search) y error (.empty.is-error). .empty-compact reduce el padding.

Sin clases programadas No hay bloques para hoy en el Centro Deportivo Aurora.
No hay conexión con el SII No pudimos pedir el PDF del documento. Reintenta en unos minutos.

HTML para copiar:

Ver el HTML para copiar
<div class="empty">
  <i data-lucide="calendar-x" class="empty-ico"></i>
  <span class="empty-title">Sin clases programadas</span>
  <span class="empty-text">No hay bloques para hoy en el Centro Deportivo Aurora.</span>
  <span class="empty-action">
    <button type="button" class="btn btn-primary"><i data-lucide="plus" class="nav-ico size-3"></i>Crear bloque</button>
  </span>
</div>

<div class="empty is-search empty-compact">…</div>
<div class="empty is-error empty-compact">…</div>

9 · Toasts / confirmaciones

patrón 9 / 16

Zona fija abajo-derecha (.toast-zone, autocierre ~4 s) y sus 4 tonos. Lo destructivo se confirma con modal (patrón 3), nunca con toast. .toast-zone.is-static solo para el catálogo.

Plan asignado
Full Trimestral quedó vigente hasta el 02-10-2026.
3 planes vencen esta semana
Revisa los alumnos próximos a vencer antes del sábado.
Exportando pagos
Tendrás el archivo listo en unos segundos.

HTML para copiar:

Ver el HTML para copiar
<div class="toast-zone">
  <div class="toast toast-ok" role="status">
    <i data-lucide="check-circle" class="toast-ico"></i>
    <div class="toast-body">
      <div class="toast-title">Plan asignado</div>
      <div class="toast-text">Full Trimestral quedó vigente hasta el 02-10-2026.</div>
    </div>
    <button type="button" class="toast-x" aria-label="Cerrar"><i data-lucide="x" class="nav-ico"></i></button>
  </div>
  <div class="toast toast-warn" role="status">…</div>
  <div class="toast toast-err" role="alert">
    <i data-lucide="x-circle" class="toast-ico"></i>
    <div class="toast-body">
      <div class="toast-title">No se pudo programar la notificación</div>
      <div class="toast-text">Revisa la fecha de envío e inténtalo otra vez.</div>
      <button type="button" class="toast-action"><i data-lucide="refresh-cw" class="nav-ico size-3"></i>Reintentar</button>
    </div>
    <button type="button" class="toast-x" aria-label="Cerrar"><i data-lucide="x" class="nav-ico"></i></button>
  </div>
  <div class="toast toast-info" role="status">…</div>
</div>

10 · Filtros, búsqueda y chips de filtros activos

patrón 10 / 16

Barra de filtros compacta: buscador con icono, selects con label y chips que muestran los filtros aplicados con su «x».

Plan: Full Mensual Estado: Activo Sede: Ñuñoa Limpiar los 3 filtros 137 resultados

HTML para copiar:

Ver el HTML para copiar
<div class="toolbar">
  <div class="field field-search field-search-inline">
    <i data-lucide="search" class="nav-ico size-3"></i>
    <input type="search" placeholder="Buscar alumno, plan o clase…" aria-label="Buscar alumno, plan o clase">
  </div>
  <label class="toolbar-label" for="fl-plan">Plan</label>
  <select class="field" id="fl-plan"><option selected>Full Mensual</option></select>
  <label class="toolbar-label" for="fl-estado">Estado</label>
  <select class="field" id="fl-estado"><option selected>Activo</option></select>
  <div class="toolbar-right">
    <button type="button" class="btn btn-ghost btn-xs"><i data-lucide="rotate-ccw" class="nav-ico size-3"></i>Resetear</button>
  </div>
</div>

<div class="toolbar">
  <span class="chips">
    <span class="chip-filter">Plan: Full Mensual<button type="button" class="chip-filter-x" aria-label="Quitar filtro"><i data-lucide="x" class="nav-ico"></i></button></span>
    <span class="chip-filter is-neutral">Sede: Ñuñoa<button type="button" class="chip-filter-x" aria-label="Quitar filtro"><i data-lucide="x" class="nav-ico"></i></button></span>
  </span>
  <a class="chips-clear" href="#">Limpiar los 3 filtros</a>
  <span class="card-sub mono ml-auto">137 resultados</span>
</div>

11 · Acciones por fila y menú de acciones

patrón 11 / 16

Una acción de texto con icono + hasta 2 icon-buttons; con más de 3 acciones, un menú kebab. La acción destructiva va etiquetada dentro del menú.

AlumnoPlanCuposAcciones
CVConstanza Vega Pizarro Estudiante 9 / 12 Ir a perfil
ABAndrés Bustos Mella Full Mensual 18 / 30 Ir a perfil

HTML para copiar:

Ver el HTML para copiar
<td class="td-actions">
  <span class="row-actions">
    <a class="link-action" href="#">Ir a perfil<i data-lucide="arrow-up-right" class="nav-ico size-3"></i></a>
    <a class="btn btn-xs btn-ghost btn-icon" href="tel:+56988451177" title="Llamar"><i data-lucide="phone" class="nav-ico size-3"></i></a>
    <a class="btn btn-xs btn-ghost btn-icon" href="mailto:[email protected]" title="Enviar correo"><i data-lucide="mail" class="nav-ico size-3"></i></a>
    <details class="dropdown">
      <summary class="btn btn-xs btn-ghost btn-icon" title="Más acciones" aria-label="Más acciones"><i data-lucide="more-vertical" class="nav-ico size-3"></i></summary>
      <div class="dropdown-panel">
        <div class="dropdown-label">Acciones</div>
        <button type="button" class="dropdown-item"><i data-lucide="credit-card" class="nav-ico"></i>Renovar plan</button>
        <button type="button" class="dropdown-item"><i data-lucide="snowflake" class="nav-ico"></i>Congelar plan</button>
        <div class="dropdown-sep"></div>
        <button type="button" class="dropdown-item is-danger"><i data-lucide="trash-2" class="nav-ico"></i>Eliminar alumno</button>
      </div>
    </details>
  </span>
</td>

12 · Tabs (secciones de una misma entidad)

patrón 12 / 16

Ficha de alumno. Tabs solo para secciones de la misma entidad en la misma URL; si cambia el recurso, es navegación del sidebar.

Josefa Cáceres Núñez

Activo
Teléfono+56 9 5908 3331
Registro02-07-2026
ProcedenciaInstagram

HTML para copiar:

Ver el HTML para copiar
<div class="tabs">
  <div class="tabs-list" role="tablist">
    <button type="button" class="tabs-trigger is-active" role="tab" aria-selected="true">Datos</button>
    <button type="button" class="tabs-trigger" role="tab" aria-selected="false">Planes <span class="tabs-count">3</span></button>
    <button type="button" class="tabs-trigger" role="tab" aria-selected="false">Próximas clases <span class="tabs-count">2</span></button>
    <button type="button" class="tabs-trigger" role="tab" aria-selected="false">Historial</button>
  </div>
  <div class="tabs-panel">
    <!-- contenido de la pestaña activa -->
  </div>
</div>

13 · Encabezado de página (sin breadcrumbs)

provisto por base.src.css

Toda vista arranca con esta cabecera: título con icono, contexto y acciones a la derecha. Las clases viven en base.src.css (es layout) y NO se redefinen en la capa de componentes. Sin breadcrumbs desde el 15-09-2026: el sidebar está siempre a la vista y repetir la ruta era ruido.

Lista de Alumnos

412 activos · 37 en prueba · 158 inactivos

11-09-2026

HTML para copiar:

Ver el HTML para copiar
<header class="page-head">
  <div class="page-head-main">
    <h1 class="page-title"><i data-lucide="users" class="page-title-ico"></i>Lista de Alumnos</h1>
    <p class="page-sub">412 activos · 37 en prueba · 158 inactivos</p>
  </div>
  <div class="page-actions">
    <span class="page-date">11-09-2026</span>
    <button type="button" class="btn btn-outline"><i data-lucide="download" class="nav-ico size-3"></i>Descargar</button>
    <button type="button" class="btn btn-primary"><i data-lucide="plus" class="nav-ico size-3"></i>Agregar alumno</button>
  </div>
</header>

14 · Tooltip

patrón 14 / 16

Dos formas: .tooltip + .tooltip-bubble (controlada por estado) y .has-tip[data-tip] (CSS puro al hover/focus, sin JS).

Cuenta las reservas consumidas del periodo Alumno reactivado

HTML para copiar:

Ver el HTML para copiar
<!-- controlada por estado -->
<span class="tooltip is-open">
  <button type="button" class="btn btn-xs btn-ghost btn-icon" aria-label="Asistencia"><i data-lucide="clipboard-check" class="nav-ico size-3"></i></button>
  <span class="tooltip-bubble">Cuenta las reservas consumidas del periodo</span>
</span>

<!-- CSS puro, sin JS -->
<span class="has-tip badge badge-neutral" data-tip="Volvió a clases el 03-09-2026">Alumno reactivado</span>

15 · Dropdown

abierto como demo

Menú de usuario y filtro de selección. .dropdown-panel aparece con .is-open (o dentro de <details class="dropdown">, sin JS). .is-left lo alinea a la izquierda.

HTML para copiar:

Ver el HTML para copiar
<div class="dropdown is-open">
  <button type="button" class="user-chip">
    <span class="ava ava-mint">RB</span>
    <span class="user-chip-text">
      <span class="user-chip-name">Raúl Berríos</span>
      <span class="user-chip-role">Administrador</span>
    </span>
    <i data-lucide="chevron-down" class="nav-ico size-3"></i>
  </button>
  <div class="dropdown-panel">
    <div class="dropdown-label">Administrador</div>
    <button type="button" class="dropdown-item"><i data-lucide="user" class="nav-ico"></i>Mi cuenta</button>
    <button type="button" class="dropdown-item"><i data-lucide="building" class="nav-ico"></i>Mi centro deportivo</button>
    <div class="dropdown-sep"></div>
    <button type="button" class="dropdown-item is-danger"><i data-lucide="log-out" class="nav-ico"></i>Cerrar sesión</button>
  </div>
</div>

<!-- sin JS: el toggle lo hace el <details> -->
<details class="dropdown">
  <summary class="btn btn-outline"><i data-lucide="arrow-down-up" class="nav-ico size-3"></i>Ordenar por</summary>
  <div class="dropdown-panel is-left">…</div>
</details>

16 · Barras de progreso / ocupación

patrón 16 / 16

El ancho va inline con style="width:X%" derivado del dato (única excepción permitida). Tono por variante: .is-warn, .is-danger, .is-info, .is-full.

Ocupación de las clases de hoy

Cross Training · 07:0018 / 20 · 90 %
Yoga · 09:3012 / 16 · 75 %
Spinning · 10:0021 / 25 · 84 %
Pilates · 19:0016 / 16 · lleno

Alumnos activos por género

Masculino18645,1 %
Femenino20950,7 %
No binario112,7 %
Prefiero no decir61,5 %
Barra segmentada (ocupación mixta)100 %

HTML para copiar:

Ver el HTML para copiar
<div class="bar-label"><span>Cross Training · 07:00</span><span class="bar-pct">18 / 20 · 90 %</span></div>
<div class="bar bar-lg"><span style="width:90%"></span></div>

<!-- barra en tono advertencia y llena -->
<div class="bar bar-lg is-warn"><span style="width:84%"></span></div>
<div class="bar bar-lg is-full"><span style="width:100%"></span></div>

<!-- desglose (patrón 16 en tablas/listas) -->
<div class="bd-row">
  <div class="bd-top"><span class="bd-name">Femenino</span><span class="bd-num">209</span><span class="bd-pct">50,7 %</span></div>
  <div class="bd-track"><span style="width:50.7%"></span></div>
</div>

<!-- barra segmentada -->
<div class="bar-stack">
  <span class="bg-primary" style="width:52%"></span>
  <span class="bg-secondary" style="width:26%"></span>
  <span class="bg-destructive" style="width:22%"></span>
</div>

Anexo A · Botones, campos y cards

reuso dir-a · no renombrar
.mono 412 .num 2.418

HTML para copiar:

Ver el HTML para copiar
<button type="button" class="btn btn-primary">Primario</button>
<button type="button" class="btn">Neutro</button>
<button type="button" class="btn btn-outline">Outline</button>
<button type="button" class="btn btn-ghost">Ghost</button>
<button type="button" class="btn btn-danger">Destructivo</button>
<button type="button" class="btn btn-lg btn-primary">Grande</button>
<button type="button" class="btn btn-xs">Chico</button>
<button type="button" class="btn btn-ghost btn-icon" aria-label="Icono"><i data-lucide="settings" class="nav-ico size-4"></i></button>
<button type="button" class="btn btn-primary" disabled>Deshabilitado</button>

<div class="field"><i data-lucide="search" class="field-ico"></i><input type="text" placeholder="Campo con icono"></div>
<div class="field field-lg"><input type="text" placeholder="Campo cómodo 40px"></div>
<select class="field"><option>Select 28px</option></select>

Anexo B · Calendario semanal y chip de clase

reuso dir-a · no renombrar

Grilla de 7 columnas, columna de hoy marcada con .is-today, chip con franja de color por tipo y barra de ocupación (.is-full = lleno).

Clases de Hoy

Semana del lunes 7 al domingo 13 de septiembre de 2026 · hoy viernes 11-09-2026 Cross Training Yoga Spinning Funcional Pilates HIIT Zumba
LUN2
07:00
Cross Training
09:30
Yoga
MAR2
08:0014/20
Funcional
20:009/20
HIIT
MIÉ2
07:0018/20
Cross Training
18:3021/25
Zumba
JUE1
19:0016/16
Pilates
LLENO
VIEHOY · 11-093
07:0018/20
Cross Training
10:0020/25
Spinning
19:0016/16
Pilates
LLENO
SÁB2
10:00
Cross Training
11:00
Zumba
DOM0
Sin clases programadas

HTML para copiar:

Ver el HTML para copiar
<div class="cal">
  <div class="cal-day is-today">
    <div class="cal-head">VIE<span class="badge badge-mint">HOY · 11-09</span><span class="cal-count">3</span></div>
    <div class="chip type-cross">
      <div class="chip-top"><span class="chip-time">07:00</span><span class="chip-occ">18/20</span></div>
      <div class="chip-name">Cross Training</div>
      <div class="bar"><span style="width:90%"></span></div>
    </div>
    <div class="chip type-pilates is-full">
      <div class="chip-top"><span class="chip-time">19:00</span><span class="chip-occ">16/16</span></div>
      <div class="chip-name">Pilates</div>
      <div class="bar"><span style="width:100%"></span></div>
      <span class="badge badge-red mt-0.5 justify-center">LLENO</span>
    </div>
  </div>
  <div class="cal-day"><div class="cal-head">DOM<span class="cal-count">0</span></div><div class="cal-empty">Sin clases programadas</div></div>
</div>

Patrón 18 · Movimiento

aditivo · 15-09-2026 muestra en 2 vistas

Las duraciones y las curvas son tokens (--dur-* · --ease-*): ninguna página escribe un número. Las entradas son @keyframes y las salidas las sostiene .is-closing, porque una vez que la capa sale de pantalla no hay nada que animar. Prueba los cuatro casos: lo de este recuadro se anima, el resto del catálogo no.

HOVER1
07:0018/20
Cross Training

El chip responde al mouse y al teclado con un cambio de fondo y 1 px de elevación (--dur-micro · 120 ms). Es la única animación de la muestra que no es una capa.

Qué se animaTokenEntraSaleMovimiento
Modal (fondo + panel)--dur-layer200 ms130 msEl fondo se aclara; el panel llega desde 8 px abajo
Panel inferior--dur-layer200 ms130 msSube desde el borde de abajo
Aviso (toast)--dur-control160 ms130 msAparece desde 6 px abajo
Panel en línea--dur-control160 ms130 msSe despliega desde 4 px arriba
Chip--dur-micro120 ms—Fondo + 1 px de elevación

Mientras una capa se cierra deja de capturar clics en el primer cuadro, y con prefers-reduced-motion activado todo aparece en el mismo cuadro. Nunca se anima al entrar a la pantalla: solo responde a un gesto.

Ver el HTML para copiar
<div class="modal-overlay" id="mi-modal">…</div>
<script src="../_shared/prototype.js"></script>
<script>
  nfitMov.abrir(document.getElementById('mi-modal'));                  // abre
  nfitMov.cerrar(document.getElementById('mi-modal'), function () { … }); // cierra animado
</script>