Tucano v0.37.2

Cargando

Spinner para la acción que la persona disparó y está esperando, como el botón de guardar; esqueleto para el contenido que todavía va a llegar y ya tiene una forma conocida, como la fila de la tabla. El esqueleto evita el salto: el espacio ya está reservado con el tamaño de lo que viene. Solo clases, sin JavaScript.

Spinner

Haz clic en guardar: el botón queda ocupado durante dos segundos.

Esqueleto

La forma de lo que viene, en el lugar de lo que viene.

Ejemplos

El spinner se mide en em y se pinta con currentColor, así que acompaña el lugar donde está sin ninguna variante.

Botón ocupado

aria-busy="true" con disabled. En el botón, el spinner ocupa el lugar y el tamaño del icono.

En el texto

A la altura de la letra, y en su color.

Buscando cobros…

Fila de tabla

El esqueleto puede ser cualquier elemento, incluso un <td>.

ClienteImporte

Avatar y tarjeta

is-circle queda redondo con el ancho que le des.

Cómo usar

<button class="tuc-btn is-primary" aria-busy="true" disabled>
  <span class="tuc-spinner"></span> Guardando
</button>

<span class="tuc-spinner is-lg"></span>

<div class="tuc-skeleton" style="width:60%"></div>
<span class="tuc-skeleton is-circle" style="width:36px"></span>

El esqueleto es un bloque de 1em de alto y de todo el ancho: el ancho y, cuando haga falta, el alto los decides tú. No escribas un spinner a mano, con SVG o borde propio — el toast de carga y los componentes usan este.

Ocupado no es desactivado

disabled impide el segundo clic, pero el atenuado del 50% dice "no disponible", y el botón está trabajando. Con aria-busy="true" conserva el color pleno y el cursor de espera.

Con HTMX

htmx-indicator es la clase del propio HTMX: oculta, y visible solo durante la petición. Junto al spinner, aparece y desaparece sin una línea de JavaScript.

<button class="tuc-btn is-primary" hx-post="{% url 'contract-save' contract.pk %}" hx-disabled-elt="this">
  <span class="tuc-spinner htmx-indicator"></span> Guardar
</button>

El esqueleto sirve de contenido provisional para lo que HTMX va a buscar en cuanto se abre la página. Cuando llega la respuesta, reemplaza al esqueleto en el mismo espacio, y nada salta.

<div hx-get="{% url 'customers-table' %}" hx-trigger="load" hx-swap="outerHTML">
  <span class="tuc-skeleton" style="width:60%"></span>
  <span class="tuc-skeleton" style="width:80%; margin-top:8px"></span>
</div>

Accesibilidad

El texto dice lo que está pasando, y el spinner lo confirma. "Guardando" junto al spinner se anuncia; un spinner solo es un círculo girando para quien no ve.

El esqueleto es decoración: no selecciona texto, no recibe el puntero y su texto, si lo hay, queda transparente. Con prefers-reduced-motion el brillo del esqueleto se detiene del todo, porque es solo adorno. El spinner sigue girando, más despacio: quieto, dejaría de decir "esperando" y sería un círculo cualquiera.

Clases

Clase o atributoPara qué
.tuc-spinnerCírculo girando, de 1em, en el color del texto
is-lgEn el spinner: 1.5em
.tuc-btn > .tuc-spinnerDentro del botón, del tamaño de su icono
aria-busy="true"En .tuc-btn: ocupado, con color pleno y cursor de espera, incluso con disabled
.tuc-skeletonBloque con brillo, en el lugar del contenido que viene
is-circleEn el esqueleto: redondo, con el alto igual al ancho
htmx-indicatorDe HTMX: muestra el elemento solo durante la petición