Arreglar un panel de CSS grid que se escondía en silencio detrás de otro panel
Una revisión visual de la pantalla de detalle de proyecto de Greenhouse (la vista por proyecto donde se avanza una etapa, se registra un touch, o se archiva un proyecto en la bóveda) señaló tres cosas a la vez: un layout desbalanceado, una pila de botones despareja, y un historial de touch que parecía roto. Ninguna era un error separado. Dos venían de la misma causa raíz.
El problema
La vista de detalle es un layout de dos columnas: una columna izquierda angosta para la etapa y sus acciones, una columna derecha ancha pensada para tener un panel de Files y un panel de historial de Touch apilados uno sobre el otro. Excepto que el panel de historial de Touch no aparecía en la columna derecha en absoluto. Se renderizaba al fondo de la columna izquierda, debajo del panel de acciones, mientras la columna derecha se quedaba ahí con solo Files y unos cientos de píxeles de fondo vacío debajo. En una captura de pantalla parecía un error de renderizado. No lo era, era CSS haciendo exactamente lo que se le había indicado.
Por qué pasó esto
El markup tenía tres elementos hermanos planos dentro de un contenedor display: grid; grid-template-columns: <angosta> <ancha>: el panel de acciones, el panel de Files, y el panel de historial de Touch. Sin una asignación explícita de columna, el auto-placement de CSS grid llena las celdas fila por fila: el hijo 1 va a la columna 1 fila 1, el hijo 2 va a la columna 2 fila 1, y el hijo 3 pasa a la siguiente celda disponible, que es la columna 1, fila 2. Debajo del panel de acciones. No al lado de Files, donde visualmente hacía falta que estuviera.
Esta es una trampa completamente estándar de CSS grid y es fácil pasarla por alto porque ninguna de las reglas individuales se ve mal. Hay que contar los hijos contra la cantidad de columnas para detectarla, y eso no es algo que un linter o un verificador de tipos señale.
El arreglo
Envolver los dos paneles que deberían compartir columna en un solo contenedor:
.side-col {
display: flex;
flex-direction: column;
gap: var(--space-8);
}
Ahora el grid solo ve dos elementos, el panel de acciones y la columna lateral envuelta, así que el auto-placement no puede fallar sin importar cuántos paneles terminen dentro de ese wrapper más adelante.
Los otros dos hallazgos
Los botones de acción (Advance, Touch, Vault, Show in Finder) tenían anchos intrínsecos distintos, lo cual se leía como algo visualmente no planeado. Se estiraron todos a un ancho consistente, y se agregó un divisor específicamente antes del botón Vault, ya que archivar en la bóveda es la única acción de “salida” del grupo y estaba hombro con hombro con “trabajé en esto,” no un lugar donde convenga un clic equivocado.
Por separado, un historial de touch donde nadie dejó una nota de traspaso se renderizaba como cinco marcas de tiempo idénticas y desnudas seguidas. También parecía un error. Se agregó una etiqueta discreta de “Touched, sin nota” para ese caso en vez de dejarlo en blanco.
Verificándolo
Ninguno de estos tres hallazgos es algo que una suite de pruebas pueda confirmar, tienen que ver con cómo se ve realmente la pantalla. Greenhouse tiene una configuración de automatización con WebDriver para exactamente esto: construir la app con una bandera de funcionalidad de automatización solo para depuración, apuntarla a una bóveda SQLite descartable sembrada con un proyecto que tiene touches con nota y sin nota, y ejecutar un clic real en la vista de detalle para tomarle una captura. Sembrar los datos significó escribir directamente en el esquema SQLite de la bóveda en vez de hacer clic a través de los propios temporizadores de la app, ya que las condiciones de madurez de una idea se miden en días y una sesión de navegador en vivo no puede adelantar un reloj.
La captura confirmó las tres cosas: Files y el historial de Touch ahora se apilan juntos en la columna derecha, los botones de acción quedan alineados, y los touches sin nota se leen como una etiqueta intencional en vez de un glitch de renderizado.
Lecturas relacionadas
Cuando el texto importante es el que desaparece
Una tarjeta de kanban con una etiqueta de etapa, un chip de abandono, una insignia Disponible, y sin nombre. Flexbox no sabe que "achicarse con gracia" y "achicarse hasta nada" son resultados distintos.
Seis ítems pequeños de UI, y los dos casi-desastres escondidos adentro
Un bloque de CSS que grep decía que estaba muerto pero del que dependía una prueba, y una sola línea de localStorage que rompió treinta y nueve pruebas sin relación por culpa de una actualización de Node.
Un anillo de foco que no debía estar a máxima intensidad
Una línea verde brillante debajo de la barra superior en cada inicio, un intento de captura de pantalla que terminó mostrando las ventanas equivocadas, y una muestra de color que probó las matemáticas del color pero no la respuesta.