Changelog
Lo que cambió en cada versión, de la más nueva a la más antigua. Revisa primero la sección "Antes de
actualizar" de cada versión: ahí está lo que exige cambios en tu proyecto. Las mismas notas están en
CHANGELOG.es.md.
0.37.2
Corregido
- El
<select class="tuc-input" data-tuc-select>daba scroll horizontal a la página. La regla de.tuc-inputpesaba más que la que oculta el nativo y le devolvíawidth: 100%; absoluto dentro de un padre sin posición, el nativo invisible tomaba el ancho de la página y quedaba desplazado a la derecha. Ahora el nativo oculto queda en 1px en cualquier caso — también desactivado y conmultiple—, y el envío, elrequired, elresety el<label>siguen como antes.
- El
0.37.1
Corregido
- La sugerencia aparecía sola después de cerrar un modal. El clic en un botón con
data-tuc-tipabría el<dialog>, y al cerrarlo el navegador devolvía el foco al botón — y ese foco abría la sugerencia, sin que nadie apuntara ni tabulara. En un botón que solo aparece con el hover, el globo flotaba sobre la nada. Ahora el foco solo abre la sugerencia cuando viene del teclado (:focus-visible, y no justo después de un clic);Tabhasta el elemento la sigue mostrando, y el hover, elEscapey el toque no cambiaron.
- La sugerencia aparecía sola después de cerrar un modal. El clic en un botón con
0.37.0
Nuevo
- Grupo de botones, solo con clases:
.tuc-btn-group. Por sí solo une las acciones que van juntas —[Editar][Duplicar][Archivar]se vuelve un bloque, en vez de tres botones sueltos en la línea. Conis-segmentedviste el<input>de botón: es la caja de la pestaña segmentada, con el elegido en el color de destaque del tema, y el valor sigue siendo del nativo —name,value,required, el POST y las flechas del teclado son los del navegador. El<input>va dentro del<label class="tuc-btn">, conclass="tuc-btn__input", y queda con opacidad cero, y no escondido, para seguir siendo enfocable y anunciado. Contype="checkbox"valen varias a la vez, yis-blockocupa la línea entera. No sustituye a la pestaña segmentada: aquella cambia lo que se ve en la pantalla, esta es un campo y va en el POST.
- Grupo de botones, solo con clases:
0.36.0
Nuevo
- El editor ganó variables:
variables: [{ name, label, example }]pone un botón en la barra y abre una lista al escribir{, que filtra por lo que viene después de la llave y escribe{{nome}}en el texto — texto puro, como ya lo espera la plantilla del servidor.editor.unknownVariables()señala lo que está escrito en el texto y no está en la lista, la errata de siempre. En el texto la variable aparece con un fondo suave, y la que no está en la lista sale en el tono de error — el navegador pinta sobre el tramo, sin marcación en el contenido, así que el valor guardado no cambia. Dentro de un bloque de código la lista no se abre y no se señala nada — ahí se escribe código, incluido el{{ nome }}de una plantilla como ejemplo. Sinvariables, nada cambia en el editor.
Cambió
- El menú desplegable abierto con clic ya no destaca el primer elemento: con el puntero en otro lado, un elemento destacado parecía una elección ya hecha. La primera flecha es la que destaca. Abierto con el teclado (
Enter,Espacioo flecha en el disparador), el primero sigue naciendo destacado. Vale también para el menú del botón derecho y para la lista de variables, que son el mismo menú.
- El editor ganó variables:
0.35.0
Nuevo
- Menú del botón derecho (
ContextMenu,data-tuc-contextmenu): el mismo menú desplegable, abierto en el punto del clic.matchdice qué parte del área es el objetivo,itemstambién acepta una función para montar las acciones de la fila clicada, y el menú del navegador sigue conShift+ botón derecho. La tecla de menú yShift+F10abren desde el objetivo con foco.
Cambió
- El título de grupo del menú desplegable dejó de ir en mayúsculas. "CONTRATO" gritaba más que los propios elementos del menú.
- Menú del botón derecho (
0.34.0
Antes de actualizar
- El valor de un editor vacío pasó de
<p><br></p>a'', engetValue()y en el<textarea>que va en el POST. Quien reconocía el vacío comparando con<p><br></p>, en JavaScript o en el servidor, pasa a recibir una cadena vacía — y un camporequiredahora bloquea el envío, como debía. - Con el script cargado con
defer, la inicialización automática ahora espera aDOMContentLoaded, en lugar de ejecutarse en el instante en que corre el script. Es lo que da tiempo a llamar aTucano.setTexts()antes de que los componentes se monten. Un script tuyo, también condefer, que leíaelemento._tucanonada más ejecutarse pasa a encontrarundefined: léelo dentro de un listener deDOMContentLoaded. - El formato de moneda en reales pasó de
realabrl, en inglés como los demás nombres de código:data-tuc-mask="brl",data-tuc-format="brl",format: 'brl'yTucano.FORMATS.brl.realdejó de funcionar: el campo queda sin máscara y el texto de visualización aparece crudo. Tucano.mask.format(valor, 'document'), alias no documentado de'cpf-cnpj', fue eliminado. Usa'cpf-cnpj'.- Los eventos de la tabla ganaron el prefijo de los demás:
tuc:sortahora estucano:sort, ytuc:selectestucano:select. Los nombres antiguos ya no se disparan. - Se eliminó la opción
openOnFocusdel date picker. Existía solo para mantener el comportamiento anterior de abrir el calendario al llegar conTab; abrir sigue siendo↓,Espaciocon el campo vacío o clic. - La búsqueda en el servidor del select lee solo los formatos de respuesta documentados:
[{value, label}],["a", "b"],{results: [...]}de DRF y{id, text}de Select2, connextpara saber si hay otra página.{items},{data},pk,nameyhas_moredejaron de leerse: responde en uno de los formatos anteriores o usaloadOptions. - Nombres en portugués que quedaban en el código:
Popoverpasa aonDismisslos motivos'focus'y'detached'(eran'foco'y'solto'), y la custom property del área del color picker es--hue(era--matiz). - Se quitaron clases de estado que ninguna regla de CSS leía —
is-multipleeis-emptydel select,is-emptydel upload,is-rangeeis-timeddel date picker — y la propiedadidde la instancia deTable, que nada usaba. Si tu proyecto dependía de ellas, usa.tuc-select-native[multiple] + .tuc-select,.tuc-select:not(.has-value),instancia.isRange,instancia.opts.timey elidde la propia<table>. - El CSS quedó casi 1 KB más pequeño (gzip) sin los fallbacks que Tailwind inyectaba para navegadores antiguos. Por debajo de Chrome 111, Safari 16.2 y Firefox 113 — la base del propio Tailwind 4 —, los fondos suaves, los anillos de foco y el riel del interruptor apagado, que usan
color-mix, dejan de verse. Y los pesos de fuente de los componentes quedan fijos en 500 y 600, sin leer el tema de Tailwind de tu proyecto. - Date picker con el botón Aplicar (el predeterminado con
time, oautoApply: false): elegir día, hora o atajo ya no disparatucano:change,changenionChange. El evento sale una vez, en Aplicar, y cerrar conEscapeo un clic fuera descarta la elección. Antes cada clic ya emitía, Aplicar emitía otra vez y cerrar fuera mantenía el cambio. ConautoApply: truenada cambia. Quien guardaba en cada evento pasa a recibir solo el valor confirmado. - Una fecha fuera de
minymaxya no se lleva al límite. Escrita, se rechaza y queda el valor anterior; ensetValue()y en elvalueinicial, el campo queda vacío, como ya pasaba condisabledDates. Antes2027-01-15conmaxen2026-12-31se convertía en 31/12/2026 en silencio. Un rango escrito sin un fin válido también se rechaza entero, en lugar de quedarse solo con el inicio. Tucano.dates.parseISO()lee solo ISO (aaaa-mm-dd, con hora opcional) yDate. Un texto en otro formato caía ennew Date(texto), que lee07/09/2026como 9 de julio, y ahora devuelvenull. Para lo que la persona escribe, useTucano.dates.parseUserInput().- En el color picker, el
changenativo sale una sola vez, cuando termina el arrastre en el área o en las barras, como en el<input type="range">. Eltucano:changey elonChangesiguen saliendo en cada movimiento. Antes el nativo salía en cada píxel, y unhx-trigger="change"enviaba una petición por movimiento del ratón; quien usaba elchangepara una vista previa en vivo pasa a escuchar eltucano:change. - El tono del color picker se detiene en 360 con el teclado, en lugar de dar la vuelta a 0:
→al final de la barra ya no hace nada.HomeyEndvan a los extremos. - La subida directa solo envía el
X-CSRFTokenleído de la cookie al mismo origen de la página, como en la receta de Django. Antes iba junto al archivo a cualquierurl, incluso de otro dominio. Si subes a otro origen y necesitas el token, pasaheaders: { 'X-CSRFToken': ... }. - En la subida directa de un input con
name, una respuesta 2xx sin el id (responseId) deja el archivo en error, con "O servidor não devolveu o id". Antes quedaba listo, con la marca, y el formulario no enviaba nada. - El campo de color sin
valuenace vacío, en lugar de venir con un color que el componente elegía solo. Ahorarequiredbloquea el envío mientras nadie elige, y el formulario ya no envía un color que nadie pidió.getValue()devuelvenullen ese estado, ysetValue(null)osetValue('')lo limpia. Quien contaba con el color de fábrica ponevalue="#4f46e5"en el campo. - En el select,
setValue(valor, { silent: true })yclear({ silent: true })pasan a contener también elchangedel elemento nativo, y no solo elonChangey eltucano:change. Es lo que hace el DOM cuando un script escribe enselect.value. Unhx-trigger="change"dejaba de ser silencioso y mandaba una petición en cada cambio por código. Llama sinsilentpara avisar; elegir con el ratón o el teclado sigue disparando.
Nuevo
data-tuc-revealtambién en texto suelto en la pantalla, y no solo en campos: un CPF en un perfil, la tarjeta en una celda de tabla, una clave de API en un párrafo. El texto aparece oculto, con el ojo al lado, en los mismos modos (end,email,all) y junto condata-tuc-format. Es solo visual: el valor completo sigue en el HTML, así que lo que no puede llegar al navegador debe ocultarse en el servidor.Tucano.setTexts()reemplaza cualquier texto que los componentes muestran o anuncian: el "Limpar" y el "Aplicar" del date picker, los atajos de período, el "Buscar..." y el "Nenhum resultado" del select, el "Fechar" del modal, del panel lateral y del toast, los botones del editor, el "Mostrar"/"Ocultar" de la máscara y las etiquetas que lee el lector de pantalla. En un proyecto en inglés o español ya no aparece nada en portugués. El cambio es por grupo (Tucano.setTexts({ datepicker: { clear: 'Clear' } })), vale para lo que se monte después, y la opción de la instancia (data-placeholder,emptyText,prevText,textsdel upload) sigue ganando. El portugués sigue como predeterminado, sin diccionarios de idiomas en el paquete, yTucano.getTexts()devuelve los textos actuales. El nombre del día que el lector de pantalla lee en el calendario ahora viene del idioma de la página.- Tipos de TypeScript en el paquete, en
dist/tucano.d.ts, generados a partir del código en cada build y sin ningún peso en el bundle.import { DatePicker } from 'tucano'y elTucanoglobal del<script>(concheckJs) pasan a tener autocompletado y verificación de opciones, métodos, lo quegetValue()devuelve en cada modo, eldetailde los eventostucano:*, los grupos y claves deTucano.setTexts()y las utilidadesTucano.mask,Tucano.datesyTucano.color.
Cambió
- El icono de
.tuc-alertqueda en el medio de la altura del aviso, y ya no pegado a la primera línea. Con título y texto subía solo, mientras que los botones de acción al lado ya quedaban centrados.
Corregido
- El select no disparaba
inputen el<select>nativo, solochange. El del navegador dispara los dos, en ese orden: unhx-trigger="input"nunca se ejecutaba, y en Firefox el globo de validación de un envío inválido no se cerraba cuando la persona elegía la opción. data-tuc-revealen un campo sindata-tuc-mask, como contraseña y token, lanzaba un error en cada tecla.- Un campo de contraseña vacío con
data-tuc-revealnacía visible, cambiado atype="text", y mostraba lo que se escribía. Ahora nace siempre oculto. - Un campo solo con el ojo recibía
inputmode="numeric", y el móvil abría el teclado de números para contraseñas y tokens. Y el campo de contraseña perdía elautocompletedel navegador, lo que estorbaba al gestor de contraseñas. - Algunos textos predeterminados en portugués no tenían tilde: "Mês anterior", "Próximo mês", "Próximo" y "Selecionar período" en el date picker, "Limpar seleção" en el select y "Saturação e brilho" en el color picker. Si un test de tu proyecto compara esos textos, actualízalo.
Escapeen un select, calendario o color picker abierto dentro de un modal cerraba también el modal. Ahora cierra solo el panel.Escapeen el color picker dejaba el foco en<body>, y el siguienteTabvolvía a empezar desde arriba de la página. El foco vuelve a la muestra, como en los demás campos.- El tablero de ajedrez detrás de un color translúcido — en la muestra, la vista previa y la pista de transparencia del color picker — no aparecía.
- Select, date picker, color picker, menú y tooltip salían del DOM en el instante exacto en que terminaría la animación de salida, y el final podía verse cortado.
- Período escrito en el date picker:
25-12-2025 a 31-12-2025se cortaba en los guiones de la fecha,aayaévalían como separador, y el "AM" de una hora de 12 horas partía el texto. Los separadores ahora sona,atéy-entre espacios, y–o—. - Quitar un archivo en la subida directa pisaba el
X-CSRFTokenindicado enheaders; el envío ya lo respetaba. - Volver a abrir un modal o un panel lateral menos de 200 ms después de cerrarlo hacía que el diálogo se cerrara solo enseguida: el cierre programado no se cancelaba. Ahora volver a abrir cancela el cierre pendiente.
- El date picker leía fechas ambiguas en formato estadounidense en el
valueinicial y ensetValue():07/09/2026se convertía en 9 de julio en un campo en portugués, también con hora. El texto ahora pasa por la lectura del idioma, y unDateentra tal cual. - Una fecha escrita en el date picker no disparaba
tucano:changenionChange,Entercon el panel abierto no confirmaba ni cerraba yEscapeno descartaba el texto: la vista previa grababa el valor mientras se escribía. - Empezar un rango nuevo y cerrar con
Escapeo un clic fuera borraba el rango que ya estaba elegido. Ahora vuelve. - Cerrar y volver a abrir en menos de 200 ms el date picker, el select, el color picker, el menú o la ayuda sacaba el panel del DOM con el componente todavía abierto.
- Foco con el teclado en el calendario: la flecha sobre un día desactivado mandaba el foco al
<body>; abrir con↓enfocaba el día 1, desactivado cuandomincae a mitad de mes, en lugar del día elegido o de hoy; y con dos meses el día repetido del mes vecino recibía el foco, con dos paradas de Tab en la cuadrícula. - Hacer clic o pulsar
Enteren las flechas, la etiqueta del mes, las celdas de mes y año, los atajos y las horas del calendario mandaba el foco al<body>. - Número de semana incorrecto en el calendario cuando la semana empieza en domingo, como en pt-BR y en-US: salía el de la semana anterior.
- Columnas de hora del date picker: cada botón era una parada de Tab (194 con segundos) y las flechas no hacían nada. Ahora cada columna es una sola parada,
↑,↓,HomeyEndse mueven en ella, yEnteroEspacioeligen. destroy()del date picker dejaba el campo sinname, y el formulario dejaba de enviarlo, además de los atributos, la clase ydata-tuc-ready, que impedía aTucano.initmontarlo de nuevo; en modo nativo quedaban el envoltorio y el overlay. Ynew DatePickerdos veces en el mismo campo creaba dos instancias: la segunda ahora reemplaza a la primera.form.reset()dejaba el date picker desincronizado: el campo mostraba el texto crudo delvaluey el hidden seguía con el valor anterior.- Date picker: en modo nativo con hora,
maxbloqueaba todas las horas del último día; los atajos de rango con hora terminaban a medianoche ("Hoje" era 00:00 — 00:00); en un idioma de 12 horas la hora del panel salía en 24; ydata-native="auto"no se leía. - Las vistas de mes y de año del calendario ignoraban
minymax. Ahora lo que queda fuera está desactivado, y las flechas también. - El diseño compacto del date picker se decidía solo al montar: ensanchar la pantalla o girar la tableta dejaba el campo sin escritura y sin máscara.
- La cuadrícula del calendario no tenía
role="row", y la región que anuncia el cambio de mes se recreaba en cada render, así que el lector de pantalla no la anunciaba. - Arrastrar un fragmento de otra página dentro del editor traía el HTML consigo — título, color, estilo e
<img>, que el navegador llegaba a descargar. Soltar ahora entra como texto plano, como pegar. - El filtro del editor aceptaba
//sitio.comy/\sitio.comcomo ruta local, y el enlace guardado apuntaba a otro dominio. - Caja de enlace del editor: un
javascript:escrito se volvía un enlace clicable en el área (el valor guardado salía limpio); una dirección sin esquema, comoejemplo.com, desaparecía en silencio al guardar y ahora recibehttps://; y cambiar la dirección con el cursor dentro del enlace lo partía en dos. Entery pegar dentro de un bloque de código del editor perdían los saltos de línea al repintar, y las líneas se juntaban en una sola.Taben una tabla del editor avanzaba una sola celda y no salía de una celda vacía. Ahora las recorre todas y crea una fila en la última.- El
placeholderdel editor nunca aparecía. requireden el editor no funcionaba: sin tocar, bloqueaba el envío sin mostrar dónde; vaciado, enviaba<p><br></p>y pasaba. Y elresetdel formulario no devolvía el editor al contenido original.- Una tabla insertada en el editor quedaba dentro del párrafo del cursor, dejaba un
<p></p>de más en el valor, y el siguienteCtrl+Zdeshacía el texto y dejaba la tabla. - Seleccionar texto en negrita fuera del editor encendía el botón de negrita de todos los editores de la página.
- Una lista aplicada a un párrafo dejaba
<p></p>antes y después de ella en el valor guardado. destroy()del editor dejaba_tucanoy la clase en el textarea, y el repintado programado seguía corriendo.- En Safari,
Enterdentro de un bloque de código del editor abría un bloque nuevo en lugar de partir la línea, y pegar o soltar texto de varias líneas ahí se convertía en un bloque por línea. - En Safari, el botón de la barra del editor activado con el teclado (
Tabhasta él yEspaciooEnter) aplicaba el comando a un cursor vacío al principio del texto, y no al fragmento seleccionado. - En Firefox,
Ctrl+Zjusto después de insertar una tabla en el editor no la quitaba. - En Firefox, cambiar la dirección de un enlace con el cursor dentro dejaba un
<a>vacío delante del enlace, en el valor guardado. - El panel del color picker no se alcanzaba con el teclado: con el foco en la muestra, el siguiente
Tabsalía del campo y el panel se cerraba. Abierto con↓, o conEnteryEspacioen la muestra, el foco ahora entra en el área de color, y elTabrecorre el panel por dentro. Las barras ganaronHomeyEnd. Tucano.color.parseColor()y el color picker grababan basura a partir de colores CSS válidos: un alfa en porcentaje, comorgb(255 0 0 / 50%), salía#ff0000NaN, yhsl(120, 200%, 50%)salía#-7f17f-7f. Ahorargb()yhsl()leen%, la barra del alfa,degyturn, cada parte se limita a su rango, y lo que no es número rechaza el color.Tucano.color.formatColor()devolvíahsl(360, …)para un tono cerca del final, que al releerse pasaba a 0, y#rrggbbffpara opacidad de 0,998 en adelante.- Escribir un color en el campo del color picker disparaba el
changenativo dos veces — con HTMX, dos peticiones —, y una tecla en el borde del área emitía otra vez el mismo valor. form.reset()dejaba la muestra y la instancia del color picker con el color anterior.- Un color picker desactivado, de solo lectura o dentro de un
<fieldset disabled>abría el panel y dejaba cambiar el color. - Con
alpha: false, un valor inicial con opacidad, como#ff000080, quedaba en el campo del color picker con la barra de opacidad oculta. destroy()del color picker dejabadata-tuc-ready, yTucano.initno volvía a montar el campo. Ynew ColorPickerdos veces en el mismo campo anidaba un control dentro del otro, con dos muestras: la segunda ahora reemplaza a la primera.- Paleta del color picker:
data-swatchesconrgb(255, 0, 0)se partía en las comas y daba tres muestras rotas; la marca ignoraba la opacidad, y#00ff0080y#00ff00se encendían juntas; y el aumento al pasar el ratón no se animaba. - Color picker: un texto inválido en el campo del panel se quedaba ahí después de confirmar, falseando el valor; el botón derecho en el área cambiaba el color junto con el menú contextual; y gris o negro con
setValue()o escritos llevaban el área al rojo, en lugar de mantener el tono. - Subida de un solo archivo: elegir un archivo rechazado borraba el que ya estaba elegido, y en modo directo además llamaba a su
DELETEen el servidor. - Subida en el formulario: el
resetvaciaba el input, pero la lista seguía mostrando archivos que el envío ya no llevaba. destroy()de la subida en medio de un envío dejaba seguir la petición y aún emitíatucano:change; en modo directo el input volvía sinname.- Subida: el input nativo oculto era una parada de
Tabsin foco visible, y quitar un archivo — o que otro terminara de subir — mandaba el foco al<body>. - Subida dentro de un
<label>: hacer clic en la zona abría la ventana de archivos dos veces en Firefox y Safari. - Una subida desactivada, en el input o en un
fieldset, aceptaba archivos soltados en la zona, y en modo directo los enviaba. - Subida directa:
'x-csrftoken'en minúsculas enheadersse sumaba al token de la cookie; el id iba sin codificar en la URL delDELETE, y un../salía deldeleteUrl; los hidden ignoraban el atributoformdel input;clear()con un envío en curso emitía dos veces; y soltar muchos archivos a la vez redibujaba la lista por cada uno. data-max-size="2M"y otras grafías sin la "b" se volvían "sin límite" en silencio. Ahora2M,300ky1 MiBvalen, y lo que no se lee avisa en la consola.- Búsqueda del select: escribir con tilde (
pará,são) no encontraba nada — solo se normalizaba la opción, no el término escrito. - Select con búsqueda en el servidor: volver a un término aún en vuelo dejaba la lista trabada en "Buscando..."; la respuesta de un término abandonado aparecía durante el debounce y al reabrir;
minChars: 0no buscaba al abrir; y un término servido desde la caché dejaba de paginar. - Paginación del select remoto: un servidor que ignora
pagegeneraba peticiones sin fin; cargar la página siguiente devolvía el scroll y el resaltado arriba; y un error en ella borraba la página que ya estaba en pantalla. - Select dentro de un
<label>: el clic que abría el panel lo cerraba enseguida. El foco que llega al<select>nativo — por<label for>o por el aviso de campo obligatorio — va a la búsqueda, y el campo lee su nombre accesible del<label>, dearia-labelo dearia-labelledby. - Un select desactivado dejaba escribir y limpiar con la X, y no parecía desactivado. Una opción dentro de
<optgroup disabled>se podía elegir, y elBackspacedel múltiple quitaba etiquetas de opciones desactivadas. - Teclado en el select:
Enteren el múltiple después de filtrar marcaba otra opción;↑sin opción activa no iba a la última;HomeyEndse paraban en opciones desactivadas; el puntero quieto sobre la lista robaba el resaltado de las flechas (en Safari, en cada desplazamiento); yaria-activedescendantseguía apuntando a una opción que no estaba en pantalla. - Select: hacer clic en el título de un grupo, en la X de limpiar o en la X de una etiqueta quitaba el foco de la búsqueda; volver a elegir la opción ya elegida disparaba
change;setValue()con dos valores en un select simple mostraba uno y enviaba otro (vale el primero); un<option value=""></option>sin texto borraba el placeholder;destroy()dejabadata-tuc-ready; yform.reset()en modo remoto dejaba el campo vacío. refresh()del select no activaba la búsqueda cuando las opciones llegaban después del montaje, y el menú de una etiqueta larga superaba el ancho del móvil, desplazando la página de lado.
- El valor de un editor vacío pasó de
0.33.1
Corregido
- En el select simple,
BackspaceyDeletecon la búsqueda vacía no hacían nada: solo el múltiple respondía, quitando la última etiqueta. Quien llegaba con Tab a un select lleno no podía vaciarlo sin ir con el mouse a la X. Ahora las dos teclas limpian el valor, como la X. Conclearable: falseno hay X, y el teclado tampoco limpia. - Limpiar un select simple sin
<option value="">— con la X o con el teclado — mostraba el campo vacío, pero el<select>volvía solo a la primera opción y el formulario enviaba el valor anterior. Ahora el nativo queda sin nada seleccionado: el campo no se envía yrequiredbloquea el envío. - Escribir en un select con búsqueda y la lista cerrada perdía la primera letra: abría la lista, y abrirla vaciaba la búsqueda. "sa" se volvía "a". Ahora la búsqueda guarda todo lo escrito, también en el select remoto.
- El
reset()del formulario devolvía el<select>a su valor inicial, pero el componente seguía mostrando el valor anterior, porque el reset no disparachange. Ahora la pantalla acompaña el reset.
- En el select simple,
0.33.0
Antes de actualizar
- El color de acento por defecto ahora es neutro:
#0a0a0aen el tema claro y#fafafaen el oscuro, con el texto encima invertido. El color es de tu proyecto, y el paquete no impone una marca. Si no defines--tuc-accent, el botón primario, la casilla marcada, la pestaña activa y el día elegido pasarán de naranja a negro (o casi blanco, en oscuro). Para mantener el naranja, define en:root, .dark--tuc-accent: #FF7501,--tuc-accent-hover: #FF8A2A,--tuc-accent-fg: #ffffff,--tuc-thumb: #ffffffy--tuc-accent-text: #B84300— este último#FF7501en.dark. La receta completa está en la página Tema. - Los motivos que el modal y el panel lateral entregan a
onCloseahora están en inglés, como el resto de la API:'button'en lugar de'botao'y'backdrop'en lugar de'fundo'. Si tu código compara el motivo, cambia los dos. - En la máscara,
data-tuc-reveal,data-reveal-modeyrevealModepasan a serendoall(eranfimytudo), y el formatocnpj-numericopasa a sercnpj-numeric. Los nombres antiguos dejan de funcionar: cámbialos en la plantilla.
Nuevo
- El campo con
data-validatese pone verde cuando pasa. En la máscara, en cuanto el valor está completo y correcto, ya mientras se escribe (data-tuc-valid); el rojo sigue apareciendo solo al salir del campo. En un.tuc-inputnativo condata-validate, el verde viene de:user-valid. Sin el atributo, no cambia nada.
Corregido
- El panel lateral con contenido más alto que la pantalla — un menú largo, un formulario de filtros — se salía de la pantalla y no se desplazaba. Ahora el cuerpo se desplaza y el panel ocupa el alto de la pantalla, en los cuatro bordes; el modal recibió la misma corrección.
.tuc-menudentro de una columna de altura fija, como la barra lateral de un sistema, se desbordaba de la columna y se desplazaba la página entera en su lugar. Ahora el menú se desplaza por sí solo ahí; fuera de una columna así, no cambia nada.- Con un modal o un panel lateral abierto, la rueda del ratón desplazaba la página de detrás — sobre el fondo oscurecido y después de que el contenido del diálogo llegara al final. Ahora la página queda quieta mientras haya un diálogo abierto, y llegar al final del cuerpo no transmite el desplazamiento.
- La X de cerrar del modal y del panel lateral quedaba unos 2px hacia dentro de la línea donde terminan el contenido y los botones del pie. Ahora el trazo de la X termina en esa misma línea.
- Abrir un modal o un panel lateral en una página con barra de desplazamiento que ocupa espacio (Windows, o macOS con ratón) hacía saltar hacia un lado el contenido del fondo: el bloqueo de desplazamiento ocultaba la barra y la página ganaba su ancho. Ahora el espacio de la barra queda reservado mientras el diálogo está abierto.
- Una tabla con muchas columnas en el editor y en
.tuc-prosequedaba presa en el ancho disponible y apretaba el texto a una palabra por línea. Ahora cada columna tiene un ancho mínimo y la tabla ancha se desplaza en horizontal, por sí sola, sin mover el resto del texto. El HTML guardado no cambia.
- El color de acento por defecto ahora es neutro:
0.32.1
Corregido
- El campo del date picker declaraba
aria-expandedsin un rol que lo admita, y el lector de pantalla ignoraba el atributo. Ahora esrole="combobox", el rol de ARIA para un campo que abre un panel. - Date picker y select mantenían
aria-controlsapuntando al panel incluso cerrado, cuando no está en el DOM — un valor inválido para el lector de pantalla y para Lighthouse. Ahora el atributo solo existe con el panel abierto.
- El campo del date picker declaraba
0.32.0
Antes de actualizar
- El color de acento por defecto ahora es el naranja del tucán,
#FF7501, en ambos temas, con texto blanco encima (--tuc-accent-fg). El contraste del blanco sobre ese naranja es 2,7; quien necesite 4,5 en el botón primario define--tuc-accent-fg: #0a0a0aen su propio proyecto. Donde el acento es el color del propio texto — enlace, menú activo, tag — entra el nuevo--tuc-accent-text, más oscuro en el tema claro para seguir siendo legible. Quien ya define--tuc-accenten su proyecto, revise también estos dos. - El archivo rechazado en el upload es un
.tuc-alert is-danger, con la clase.tuc-upload__rejected. La regla.tuc-upload__item.is-rejectedya no existe. - El campo hex del color picker es un
.tuc-input, y el cuentagotas un.tuc-btn is-outline is-sm. - Se eliminaron las clases
tuc-upload__actionytuc-pagination__ico. - El elemento activo de
.tuc-menuya no tiene la línea en el borde izquierdo. - Etiqueta, aviso y toast de información usan el nuevo
--tuc-info(azul), y ya no el color de acento. Quien sobrescribía--tuc-accentpara cambiar ese tono pasa a sobrescribir--tuc-info.
Nuevo
- Casilla, opción e interruptor:
.tuc-radio,.tuc-switchy la etiqueta.tuc-choice, que alinea el control con la primera línea del texto, con.tuc-choicespara grupos. - Formulario:
.tuc-label,.tuc-hinty.tuc-error, y el estado inválido conaria-invalid="true"en todos los campos — Django 5 ya escribe el atributo..tuc-inputtambién sirve para el<select>nativo. - Pestañas (
data-tuc-tabs), con el teclado de ARIA APG, modo manual para paneles que cargan por HTMX y la variante segmentada. - Aviso fijo en la página (
.tuc-alert), en cuatro tonos. - Carga:
.tuc-spinnery.tuc-skeleton. Un botón conaria-busyno se atenúa. - Línea de tiempo (
.tuc-timeline), solo con clases: tonos, punto relleno o hueco e icono opcional en lugar del punto. - El paquete exporta
icon,ICON_CHECK,ICON_COPYeICON_X. - Documentación con una página por componente, generada en el build.
Cambió
- Los componentes usan por dentro las piezas de la propia biblioteca: la etiqueta y los atajos del calendario son
.tuc-btn, la carga del toast y del select es.tuc-spinner, el contador del menú es.tuc-badge. - El brillo del modal y del panel lateral sigue el color de acento.
Corregido
- El campo de moneda de la máscara nacía sin placeholder y parecía un campo común. Ahora muestra el cero ya formateado, como
R$ 0,00. - Las flechas para cambiar de mes del calendario eran invisibles y no se podían pulsar.
- Un botón hecho con
<a>aparecía subrayado. - Upload, elemento peligroso del menú desplegable y campo inválido de la máscara usaban rojo y verde fijos, que no se aclaraban en el modo oscuro.
- El anillo de foco del panel de pestañas se superponía a la lista.
- El error de la búsqueda en el servidor se mostraba igual que "ningún resultado".
- En el date picker, abrir con
↓oEspaçodejaba el foco en el campo: las flechas no llegaban a los días yTabcerraba el panel. Ahora el foco va al día. - La máscara borraba el
aria-invaliddel campo al enfocarlo, y el error que envió Django desaparecía con el primer clic. Ahora solo la validación de la propia máscara lo modifica. setValue()en el campo sensible no actualizaba el valor enviado en el formulario.- La barra del editor solo respondía al ratón: con el foco en un botón,
EnteryEspaçono hacían nada. Ahora funcionan, y el comando se aplica al texto que estaba seleccionado. - Los botones de borrar fila, columna y tabla del editor no se ponían rojos.
- La opción
methoddel upload se ignoraba, y el envío salía siempre como POST. - Un toast que venía de los mensajes de Django tomaba el tipo equivocado cuando el mensaje tenía
extra_tags: solo leía la primera palabra. Tooltip.setText()borraba la flecha junto con el texto.- Un
data-tuc-tipvacío interrumpía el montaje de los tooltips siguientes. - Un menú desplegable creado en JS con
paneldejaba los elementos sinrole="menuitem". - Select, date picker y color picker dentro de un modal o panel lateral abrían el panel detrás del diálogo. Ahora el panel nace dentro del
<dialog>abierto. - Un modal sin título quedaba sin nombre para el lector de pantalla; ahora el texto le da nombre.
- El diálogo salía del DOM 10 ms antes del fin de la animación de salida.
- En la paginación, los extremos quedaban sin nombre en el móvil, y
setPage()perdía el foco de quien navegaba con el teclado. - El date picker de período leía mal su propio valor en ISO (
2026-03-01,2026-03-15), que es lo que devuelve Django cuando el formulario vuelve con errores. - Cambiar
--tuc-accento un tono en un contenedor no cambiaba el fondo suave ni el anillo de foco, que se quedaban con el color de la raíz. - El resaltador de código pintaba el resto de la línea como comentario después de
https://, y todo color hex de CSS (#4f46e5) como comentario.
- El color de acento por defecto ahora es el naranja del tucán,
0.31.0
Antes de actualizar
- Se eliminó la clase
tuc-menu__secao. Usatuc-menu__section.
Cambió
- Suite de pruebas en el repositorio y en el CI: funciones puras, comportamiento en el navegador, teclado real, ejemplos de la documentación verificados contra el código y comprobaciones cruzadas de nombres.
Corregido
- El acordeón no exponía
node._tucano. - Modal y panel lateral anunciaban
actionscon las claves antiguas. toast.promisedocumentabacarregando/sucesso/erroen lugar deloading/success/error.
- Se eliminó la clase
0.30.2
Corregido
- La tag 0.30.1 no incluía el cambio de nombre del evento
tucano:toast-fechadoatucano:toast-closed, que npm ya publicaba. GitHub, jsDelivr y npm vuelven a tener el mismo contenido.
Nuevo
- Referencia completa de la API, generada a partir del código, dentro de
llms.txt.
- La tag 0.30.1 no incluía el cambio de nombre del evento
0.30.1
Antes de actualizar
- La API pasó a estar toda en inglés: nombres de método, opción, valor, clase CSS y evento.
Modal.abrir()pasó a seropen(),tom: 'perigo'pasó a sertone: 'danger',.tuc-gavetapasó a ser.tuc-drawer. - La tabla ordena en el servidor por defecto; ordenar en la pantalla requiere
data-sort-mode="client". - Llegar con
Tabya no abre el panel de los campos. Abrir es siempre explícito.
Nuevo
- Tabla, con ordenación y selección masiva, y paginación hecha para el Paginator.
- Menú desplegable.
- Etiqueta de estado, casilla de verificación con diseño propio y botón de copiar en los bloques de código.
- El campo dibuja el borde y la altura antes de que se ejecute el script.
Cambió
- Tokens en
:rooty reset con un solo selector.
- La API pasó a estar toda en inglés: nombres de método, opción, valor, clase CSS y evento.
0.25.1
- El navegador ancla el desplazamiento por sí solo, sin corrección manual.
0.25.0
- Importar
tucanoya no ejecuta nada: el empaquetador incluye solo lo que se usó.
- Importar
0.24.2
- Aplicar un título en el editor no hace saltar el texto, y el enlace se pide en un modal.
0.23.3
- La barra de desplazamiento sigue el tema.
0.23.1
- Mismo contenido que la 0.23.0, publicado con otro número porque npm reservó el anterior.
0.23.0
- Editor de texto con tabla, alineación y bloque de código. El campo en Markdown se eliminó, y queda un solo editor.
- El tooltip se aleja lo suficiente para que la flecha no toque el disparador.
0.22.1
- Todos los controles verificados con medición para tener la misma altura.
0.19.0
- Editor de texto que muestra el resultado mientras se escribe.
0.18.1
- La vista previa del campo formateado sustituye al campo, en lugar de apilarse.
0.18.0
- Campo de texto formateado, en Markdown.
0.17.1
- El icono ya no queda sobre el texto en los campos con icono.
0.17.0
- Estilo para el campo de texto, que la biblioteca nunca había tenido.
0.16.3
- Archivos para IA al día con la biblioteca.
0.16.2
- Ejemplo del acordeón con contenido real.
0.16.1
- Nombres genéricos en el menú de ejemplo.
0.16.0
- Submenú en el menú lateral, con guía y marcado de la rama abierta.
0.15.1
- El icono sigue el tamaño del botón.
0.15.0
- Menú lateral, y los iconos pasan a usar el botón de la biblioteca.
0.14.3
- El acordeón ya no se traba en la primera apertura.
0.14.2
- El acordeón se cierra hasta cero, y el brillo del fondo se extiende más.
0.14.1
- El final del acordeón ya no se corta, y el brillo del panel lateral nace en el lugar correcto.
0.14.0
- Acordeón sobre
<details>nativo.
- Acordeón sobre
0.13.0
- El panel lateral pasa a ser un componente propio, sobre la misma base del modal.
0.12.0
- Panel lateral (off-canvas).
0.11.1
- El
<dialog>cerrado ya no cubre la página entera. - Los tamaños anunciados pasan a salir del build.
- El
0.11.0
- Modal sobre
<dialog>nativo.
- Modal sobre
0.10.2
- Fuga de listeners en el popover.
0.10.1
- Paneles posicionados con
left/top, y no contransform.
- Paneles posicionados con
0.10.0
- Tooltip completo: cuatro lados, flecha y color configurable.
0.9.9
- El toast pasa a la esquina inferior derecha, y se corrigió el margen en el móvil.
0.9.8
- Toast de carga que se convierte en el resultado en la misma tarjeta.
0.9.7
- Las dos regiones de accesibilidad del toast pasan a ser una sola pila.
0.9.6
- Icono y botón de cerrar centrados en el toast.
0.9.5
- Nueva animación del tooltip.
0.9.4
- La pila de toasts no se cierra al mover el ratón de uno a otro.
0.9.3
- Toast y tooltip quedan fuera de la regla de 16px del móvil.
0.9.2
- Movimiento revisado y alturas verificadas.
0.9.1
- Un botón deshabilitado muestra el cursor de bloqueo.
0.9.0
- Toasts apilados y estilo de botón.
0.8.0
- Toast y tooltip.
0.7.1
- Menos peticiones en la búsqueda en el servidor.
0.7.0
- Búsqueda en el servidor en el Select.
0.6.1
- Modos de ocultar en el campo sensible, y se corrigió el campo de contraseña.
0.6.0
- Máscaras, validación de documentos y campo sensible.
0.5.2
- Tipos aceptados en el upload documentados.
0.5.1
- Se corrigió el icono de reintentar.
0.5.0
- Campo de upload.
0.4.2
- Atributos del date picker documentados en la página.
0.4.1
- Línea de valor del color picker alineada.
0.4.0
- Personalización completa con variables CSS.
- Se corrigió una recursión en el color picker.
0.3.0
- Sin zoom en el móvil al enfocar un campo, y el panel propio pasa a ser el predeterminado.
0.2.1
- Se corrigieron el modo nativo y el calendario en el móvil.
llms.txtyAGENTS.md, para que la IA sepa usar la biblioteca.
0.2.0
- Primera versión: componentes de formulario ligeros, sin dependencias.