Aviso
Lo que sigue vigente mientras la persona está en la pantalla: "tu suscripción vence en 3 días", "este contrato está bloqueado para edición". El toast es para lo que acaba de pasar y desaparece solo; un aviso que desaparece antes de ser leído no avisó. Solo clases, sin JavaScript.
Los valores de esta pantalla se actualizan cada 5 minutos.
Contrato firmado
Las dos partes firmaron el 12/09/2026.
La suscripción vence en 3 días
Renueva para no perder el acceso a los informes.
Contrato bloqueado para edición
Hay un cobro en disputa. Habla con el área financiera.
Ejemplos
Las piezas son opcionales: título, icono y acciones entran solo cuando hacen falta.
Sin tono
Sin is-* el aviso es neutro, para lo que no es ni bueno ni malo.
Borrador guardado a las 14:32.
Sin icono
El icono es el primer hijo, cuando existe; sin él el texto se pega al borde.
Mantenimiento programado
Sábado, de 22 h a 23 h.
Con dos acciones
Las acciones son los botones del sistema. En pantallas estrechas, bajan debajo del texto.
Hay cambios sin publicar.
Aparece después
La respuesta de un envío lleva role="alert" y se anuncia en el momento.
Cómo usar
Un .tuc-alert con el tono, el icono como primer hijo y el texto en .tuc-alert__body.
<div class="tuc-alert is-warning">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 9v4M12 17h.01M10.3 3.9L1.8 18a2 2 0 001.7 3h17a2 2 0 001.7-3L13.7 3.9a2 2 0 00-3.4 0z"/></svg>
<div class="tuc-alert__body">
<p class="tuc-alert__title">La suscripción vence en 3 días</p>
<p>Renueva para no perder el acceso.</p>
</div>
<div class="tuc-alert__actions">
<a class="tuc-btn is-outline is-sm" href="/subscription/">Renovar</a>
</div>
</div>El icono no viene de la biblioteca: es el SVG que pegas, y hereda el color del tono. Los de esta página, para copiar:
<!-- información -->
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 16v-4M12 8h.01M12 22a10 10 0 100-20 10 10 0 000 20z"/></svg>
<!-- éxito -->
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M22 11.1V12a10 10 0 11-5.9-9.1M22 4L12 14l-3-3"/></svg>
<!-- alerta -->
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 9v4M12 17h.01M10.3 3.9L1.8 18a2 2 0 001.7 3h17a2 2 0 001.7-3L13.7 3.9a2 2 0 00-3.4 0z"/></svg>
<!-- peligro -->
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 22a10 10 0 100-20 10 10 0 000 20zM15 9l-6 6M9 9l6 6"/></svg>En la plantilla de Django
El error que no pertenece a un campo, non_field_errors, es el caso más común. Y los mensajes de Django pueden
convertirse en aviso, en lugar de toast, cuando necesitan quedarse en la pantalla. El tono de error de Django se llama error; el del aviso,
is-danger.
{% if form.non_field_errors %}
<div class="tuc-alert is-danger">
<div class="tuc-alert__body">
<p class="tuc-alert__title">No se pudo guardar</p>
{% for error in form.non_field_errors %}<p>{{ error }}</p>{% endfor %}
</div>
</div>
{% endif %}
{% for m in messages %}
<div class="tuc-alert {% if m.level_tag == 'error' %}is-danger{% else %}is-{{ m.level_tag }}{% endif %}">
<div class="tuc-alert__body"><p>{{ m }}</p></div>
</div>
{% endfor %}El nivel debug se convierte en is-debug, que no tiene regla, y el aviso queda neutro.
Accesibilidad
role="alert" solo en el aviso que aparece después de la carga: la respuesta de un envío, un swap de HTMX.
Por qué no en todos
El aviso que ya viene en el HTML se lee junto con la página. Con role="alert" interrumpiría al lector de pantalla sin motivo, y en una página con tres avisos, tres veces. Lo que llega después necesita el rol justamente para interrumpir: sin él, la respuesta del envío aparece en la pantalla y nadie que use lector de pantalla se entera.
{# respuesta parcial de HTMX: aparece después, así que interrumpe #}
<div class="tuc-alert is-success" role="alert">
<div class="tuc-alert__body"><p>Propuesta enviada a {{ customer.email }}.</p></div>
</div>El icono lleva aria-hidden="true": quien dice lo que pasó es el texto, y el tono no puede ser la única pista.
Color
El fondo es un tinte suave del tono sobre --tuc-bg, y no el -soft transparente de los
tokens: sobre una tarjeta de color o una imagen, el transparente dejaría el texto sin contraste garantizado.
Los tonos leen --tuc-info, --tuc-success, --tuc-warning y --tuc-danger, y
nunca --tuc-accent. La marca puede ser de cualquier color, y el significado no puede cambiar con ella. Por eso la
información ganó un tono propio: con el acento naranja, el aviso de información quedaba igual al de alerta.
Clases
| Clase o atributo | Para qué |
|---|---|
.tuc-alert | El aviso. Sin tono, neutro |
is-info is-success is-warning is-danger | El tono |
> svg | Icono, como primer hijo: 16px, centrado en la primera línea, en el color del tono |
.tuc-alert__body | El texto; ocupa el espacio que sobra |
.tuc-alert__title | Primera línea en negrita. El resto del cuerpo queda en el color secundario |
.tuc-alert__actions | Botones a la derecha; por debajo de 40rem, bajan debajo del texto |
role="alert" | Solo en lo que aparece después de la carga |
--tuc-alert-tone | El color que elige el tono; fondo, borde e icono salen de él |