Design system text+

Design system text+

Diez años de app, dos plataformas y ningún lenguaje común. El sistema empezó por contar lo que había antes de decidir nada.
Cliente TextPlus
Rol Product Designer
Año 2026
Estado Entregado

01 El problema

text+ es una app de mensajería y llamadas con más de diez años en iOS y Android. Nunca tuvo un sistema de diseño formal: los estilos vivían en el código, cada plataforma hacía lo suyo y las inconsistencias crecían con cada release. La reescritura de la app en Flutter ya estaba en marcha cuando entré.

Antes de definir un solo token hice un inventario completo de la interfaz: ocho flujos, 216 pantallas en las dos plataformas, 571 elementos clasificados por lo que hacen y no por cómo se ven. Agrupar por función y no por color fue la decisión que dio sentido a todo lo demás: dos botones “Continuar”, uno amarillo y otro verde, son el mismo botón mal implementado dos veces, no dos componentes.

Frecuencia por varianza: lo más usado y más inconsistente es lo primero que se construye.
La fila de lista es el esqueleto de la app: chats, llamadas, contactos y ajustes son la misma pieza con distinto contenido.

Mi papel

Fui el único diseñador del proyecto, en un equipo de tres: el CEO, que fijaba prioridades; un desarrollador Flutter, mi interlocutor técnico en cada decisión; y yo. Dos restricciones: un equipo así no puede mantener un sistema complejo, y el desarrollador iba a construir pantallas a partir de él sin que yo revisara cada una, así que nada podía quedar implícito.

  • Auditoría de 216 pantallas y 571 elementos
  • Arquitectura de tokens en tres modos
  • Kit de 15 componentes con auto layout
  • Reglas de uso escritas con su razón
  • Documentación del sistema
  • Handoff al theme de Flutter

02 Las decisiones

Un sistema para un equipo de tres obliga a decidir pocas cosas y dejarlas por escrito. Estas seis son la base del gobierno del sistema; cada una está documentada con su razón, para discutirla en vez de reinventarla.

01

Los tokens describen roles, nunca colores

brand/action, no brand/tangerine. Si el nombre es un color, el nombre está mal. El grupo de marca tiene exactamente dos tokens, acción y énfasis, y no admite un tercero.

Un color cambia en un sitio y ningún nombre se queda obsoleto.

02

Dos niveles en vez de tres

Primitivos y semánticos. Los tokens de componente añaden un mantenimiento que un equipo pequeño no puede pagar. En su lugar, cada componente lleva una descripción con la intención y los tokens que consume.

El sistema crece sin que crezca su mantenimiento.

03

OKLCH para que los modos sean configuración

Ocho paletas en un espacio perceptualmente uniforme: la misma luminosidad se percibe igual en cualquier tono. El modo oscuro deja de ser un proyecto de diseño y pasa a ser un cambio de modo en una variable. El contraste AA se comprueba en el par de tokens y se corrige en la variable.

Tres modos desde los mismos 67 tokens, sin repintar.

04

El amarillo actúa, el verde confirma

Nunca compiten en la misma pantalla. En los modos oscuros el amarillo se sustituye por lima de forma automática, porque el token de acción resuelve a otro valor. Todo lo que no es la acción principal es secundario o un enlace.

Una sola acción primaria por pantalla, también en oscuro.

05

Material 3 nativo, sin widgets propios

El contrato es simple: ThemeData y ThemeExtension, sin clases de widget propias. Por eso el sistema se apoya en los widgets nativos de Material 3, y los estados hover y pressed no se exportan: los gestiona Flutter, no Figma.

El desarrollador consume tokens desde el theme, sin traducción.

06

Un suelo de dispositivo real

Anchura mínima de 360 dp, de los datos de Android; altura mínima de 667 pt, del tráfico real en iPhone 7 y 8. Por debajo, un breakpoint de Flutter oculta o recoloca: comportamiento definido, no un bug. Tablet y escritorio esperan a tener datos.

Todo componente cabe en 360 × 667 y lo demás queda fuera de alcance.

Los mismos 67 tokens semánticos en Light, Carbon y Navy. El token no cambia; cambia el valor.

03 El sistema

Cinco capas, de abajo arriba. Cada una se apoya en la anterior y ninguna se salta a la siguiente: un componente nunca toca un primitivo, y una regla nunca nombra un color.

Las capas del sistema
  1. 01 Primitivos 83 variables Ocho paletas OKLCH con la misma luminosidad en cada paso
  2. 02 Semánticos 67 × 3 modos Roles, no colores: scheme, brand, feedback, text, button, stroke, avatar
  3. 03 Escalas 13 espaciados · 7 radios · 107 tipográficos Zilla Slab en los titulares grandes, Inter en todo lo demás
  4. 04 Componentes 15 sets Auto layout, cada relleno vinculado a una variable, contratos cerrados
  5. 05 Reglas y theme Guías de uso · ThemeData Cuándo se usa cada cosa, y el mismo token en Figma y en Flutter

Tokens. 277 variables en Figma, la única fuente de verdad del sistema. El espaciado funciona por bandas: de 4 a 8 dentro de un componente, de 12 a 20 como padding, de 24 a 40 entre secciones. Cruzar de banda rompe el ritmo, y está escrito.

La escala se nombra por su valor y se usa por bandas. Nunca se salta de una a otra.

Kit de componentes. Quince sets construidos sobre los tokens: botón, botón social, fila de lista, campo de texto, switch, radio, checkbox, control segmentado, tarjeta de acción, avatar, badge, selector de plan, tabs, barra inferior y barra superior. Cada set lleva su descripción con la arquitectura de capas, los tokens que consume y las notas de entrega para Flutter.

Dieciocho variantes. Hover y pressed no están: los resuelve el theme de Flutter.

La fila de lista como contrato. Es el componente que más pantallas desbloquea, así que tiene un contrato cerrado que funciona como su API: el elemento izquierdo puede ser nada, icono o avatar; el derecho es una lista fija de nueve opciones, de chevron a switch, badge o valor. No entra un tipo nuevo sin actualizar la especificación primero. En Flutter ese contrato es una enumeración, no un widget libre.

Una fila, tres slots. Las 47 versiones de la app caben aquí.
El chrome de la app: barra superior neutra, tabs y barra inferior atadas a los tokens.

Cambio de tema en un clic. Las pantallas de referencia están duplicadas cambiando solo el modo de la variable en la sección. Sin repintar nada.

Arriba Light, abajo Carbon. La única diferencia es el modo seleccionado en la sección.

Iconografía. La app mezclaba iconos de varias épocas y pesos. En vez de comprar un set nuevo, consolidé el que ya existía en la empresa: una sola librería, trazo 1.5, línea, 24 px de base, y la regla de que ningún icono se dibuja a mano.

04 Resultados

Botón primario 44 versiones repartidas por la app Un set de 18 variantes con reglas de uso: cuándo primario, cuándo secundario, qué pasa con dos acciones
Fila de lista 47 implementaciones distintas, ninguna como componente Un componente con contrato cerrado, que en Flutter es una enumeración
Color y tema Estilos sueltos en el código, un modo 277 variables como única fuente de verdad y tres modos desde los mismos tokens, comprobados en flujos reales
Entrega Handoff conversacional, pantalla a pantalla Quince componentes con notas de handoff, consumidos desde el theme de Flutter sin traducción intermedia
Documentación Decisiones en la cabeza de quien las tomó Cada decisión publicada con su razón en un sitio propio, el siguiente caso de este portfolio

05 Aprendizajes

  1. Auditar antes de tokenizar.

    El inventario no fue trabajo previo: fue la decisión de diseño más importante del proyecto. Sacó a la luz el componente que más pantallas resolvía y que nadie había pedido.

  2. Las reglas valen más que las piezas.

    Un kit sin reglas produce decisiones a ojo en cada pantalla. Escribir cuándo se usa cada cosa, y por qué, es lo que convierte una librería en un sistema y lo que permite que otros decidan sin preguntarme.

  3. Diseñar para que lo lea una máquina.

    Nombres por rol, intención documentada, contratos cerrados. Es lo que permite que el desarrollador, o quien llegue nuevo, construya una pantalla y salga parecida a lo que el sistema pretende.

Un sistema de diseño no es un entregable. Es una decisión sobre quién puede cambiar qué sin pedir permiso.

216 pantallas auditadas 8 flujos en iOS y Android, antes de definir un solo token
3 modos desde un solo token Light, Carbon y Navy: cambiar de tema es cambiar un modo
15 sets de componentes auto layout, cada relleno vinculado a una variable, notas para Flutter
47 → 1 versiones de la fila de lista un contrato cerrado con slots sustituye a todas

¿Tienes un producto que necesita escalar con criterio?

Hablemos. hola@franmarrero.com