Estilizando Discourse con variables: Un caso para una semántica más simple

Continuando la discusión de Estilizando Discourse con variables: Muestra y cuenta:

Aprecio totalmente el esfuerzo por mejorar la experiencia de tematización de Discourse. Sin embargo, no estoy completamente convencido de que el enfoque de añadir muchas variables CSS como se comparte en el tema anterior sea la solución óptima. Quería compartir algunas ideas sobre por qué.

He estado experimentando con este enfoque yo mismo a través de la Plantilla de Tema Canvas, que esencialmente proporciona una colección de variables ajustables para construir temas base:

:root {
  /* Layout */
  --d-max-width: 1110px;
  --canvas-nav-space: 0.75rem;
  --canvas-content-padding: 1.5rem;
  --canvas-topic-list-padding: 0.8em;

  /* Base Styles */
  --canvas-background: var(--secondary);
  --canvas-surface: var(--secondary);
  --canvas-border: 1px solid var(--primary-500);
  --canvas-border-light: 1px solid var(--primary-200);

  /* Border Radius */
  --d-border-radius: 2px;
  --d-border-radius-large: 2px;
  --d-button-border-radius: 2px;
  --d-input-border-radius: var(--d-button-border-radius);
  --d-nav-pill-border-radius: var(--d-button-border-radius);

  /* Button Styles */
  --canvas-button-padding: 0.5em 0.65em;
  --canvas-button-primary-padding: 0.5em 0.65em;

  /* Header */
  --canvas-header-height: 4rem;
  --canvas-header-background: var(--header_background);
  --canvas-header-border: none;
  --canvas-header-shadow: var(--shadow-header);

  /* Sidebar */
  --d-sidebar-width: 17em;
  --d-sidebar-background: var(--secondary);
  --canvas-sidebar-border: 1px solid var(--primary-low);
  --canvas-sidebar-scrollbar: var(--scrollbarWidth);
  --d-sidebar-row-height: 2.2em;
  --d-sidebar-highlight-background: var(--primary-low);

  /* Y varias más... */
}

Si bien esto funciona razonablemente bien para ajustes simples, me he encontrado con varias limitaciones al intentar escalar este enfoque:

Sobrecarga Cognitiva y Descubrimiento

Una lista extensa de variables requiere esencialmente una tabla de consulta. Esto se siente desconectado de cómo trabajarías típicamente en un framework basado en componentes, donde realmente esperarías estilizar componentes. Y tal vez sea solo yo, pero siento que cambia el modelo mental de “Quiero estilizar este componente” a “Necesito encontrar el nombre de variable correcto”.

Falta de Lógica de Cascada

La implementación actual asigna valores codificados directamente a las variables sin establecer una jerarquía de cascada adecuada:

--d-sidebar-link-color: var(--primary-high);
--d-nav-background-color--active: transparent;
--table-border-width: 1px;

Esto significa que no hay herencia de variables más generales como --link-color o --border-width. Si quiero hacer cambios sistemáticos, necesito actualizar múltiples variables específicas en lugar de cambiar un valor fundamental.

Brecha Diseño-Desarrollo

Creo que el enfoque crea fricción al trabajar entre herramientas de diseño (como Figma) y la implementación. Los sistemas de diseño suelen utilizar variables semánticas que no se mapean uno a uno con estas variables tan específicas de la implementación.

Un enfoque alternativo que abraza la arquitectura de componentes

Creo que podríamos lograr el mismo objetivo de forma más natural combinando variables semánticas básicas con una segmentación de componentes fiable. En lugar de tener una larga lista de variables específicas, ¿qué pasaría si pudiéramos contar con clases de componentes únicas y con nombres consistentes en todo Discourse? Cosas como .d-sidebar, .d-topic-list, .d-header.

Luego, combínalo con un conjunto más pequeño de variables fundamentales que realmente cascada de la manera en que CSS está destinado a funcionar:

/* Establece la base del diseño */
:root {
  --d-border-width: 2px;
  --d-surface-color: #3498db;
  --d-space-1: 1rem;
}

/* Sobrescribe a nivel de componente cuando necesites hacerlo */
.d-topic-list,
.d-sidebar {
  --d-border-width: 1px;
}

Para mí, esto se parece más a cómo funciona CSS de forma natural. Establezco mis estilos globales, luego los refino donde es necesario. Cuando quiero cambiar el aspecto de los bordes en toda la aplicación, cambio una variable. Cuando quiero que la barra lateral sea diferente, apunto específicamente a la barra lateral.

3 Me gusta

Bueno, creo que cómo CSS funcionaría de forma natural es simplemente omitir las variables y hacer

/* Establecer la base del diseño */
body {
  border-width: 2px;
  background-color: #3498db;
  margin: 1rem;
}

/* Anular a nivel de componente cuando sea necesario */
.d-topic-list,
.d-sidebar {
  border-width: 1px;
}

Quizás soy yo que soy viejo.
El verdadero problema es este

Ejemplo: simplemente apuntar a .btn o button:

.btn {
    border: 1px solid red;
}

no apunta a los botones de publicación, pero sí apunta al enlace “vistas” y al menú de hamburguesa.

1 me gusta

Hay buenas razones para usar variables, quizás no entremos en ellas aquí. Es un buen punto, sin embargo, no discutir sobre la naturaleza de CSS. Debería haberlo expresado mejor: no se trata de su naturaleza, sino de las mejores prácticas para estilizar un framework basado en componentes. Y estoy completamente de acuerdo en que los botones son otro buen ejemplo de cómo estos no se pueden aplicar correctamente.

Mirando el panorama general, ha habido un esfuerzo concertado para modernizar el lado de JavaScript del framework frontend. Y creo que ha sido un éxito rotundo. Trabajar con estándares limpios y clases bien estructuradas es realmente agradable ahora. Para mí, como diseñador, también abrió oportunidades para construir nuevos componentes frontend de manera más fácil y eficiente.

Sin embargo, no puedo evitar la sensación de que no hay un compromiso similar para llevar el sistema de diseño al mismo nivel. Si bien agregar variables CSS para cada aspecto es ciertamente más eficiente y limpio que el enfoque actual, todavía se siente como evitar los problemas arquitectónicos más profundos: una base de código llena de declaraciones demasiado específicas y sin estilos claros con ámbito de componente. Esto se siente como una solución “más fácil” que evita el problema más difícil: alinear completamente la arquitectura de estilos con el diseño modular del framework.

Entiendo que esto implicaría mucho trabajo y problemas de compatibilidad con versiones anteriores. Pero el equipo ha abordado estos desafíos con éxito en el lado de JavaScript. Si JavaScript continúa recibiendo significativamente más recursos que los estilos, esa disparidad se reflejará en los diseños finales. Y los usuarios sentirán la diferencia, incluso si no pueden articular por qué.

Me encantaría ver la misma energía de modernización aplicada a la arquitectura CSS porque estoy convencido de que los beneficios a largo plazo tanto para la experiencia del desarrollador como del usuario serían transformadores.

5 Me gusta

El enfoque que tomamos parece estar en línea con lo que estás describiendo, así que me cuesta entender cómo lo habrías implementado de manera diferente. Definitivamente estoy abierto a comentarios y aprecio la perspectiva que aportas.

Por ejemplo, para algo como --space, cambiar esto cambiaría todo el espaciado en la aplicación. También podrías enfocarlo para que solo afecte el espaciado en la lista de temas o en la barra lateral con enfoques similares a los que describiste.

Esto es cierto para algunos elementos, pero no para otros. ¡Cualquier otro ejemplo que pudieras compartir sería genial!

Este es sin duda un problema. Un enfoque que tenemos en mente (al menos experimentalmente por ahora) es un editor en la línea de lo que shadcn está haciendo aquí:

Aunque no es un enfoque perfecto, siento que nos acercaría a facilitar las cosas a las personas que no saben cómo usar el inspector / acceder a metadatos para la documentación / usar CSS.

En cuanto a un enfoque más basado en componentes, es algo que eventualmente queremos lograr, pero Discourse tal como está no fue construido pensando en el diseño por componentes, y esperar a llegar a eso antes de agregar variables utilizables no estaba sobre la mesa.

Agregar algunas clases para que esto sea más fácil de implementar en ciertas secciones suena como un buen camino a seguir en cuanto a usabilidad.


Estoy de acuerdo contigo :+1:

2 Me gusta

La respuesta corta es no hagas esto :sweat_smile:

Es mucho mejor apuntar a una clase de botón secundaria, btn-default, btn-primary, btn-flat, estas clases secundarias representan un tipo visual de botón.

.btn y button son más ampliamente “esto es un botón” que cualquier apariencia específica.

4 Me gusta

Esto es exactamente lo que es. Actualmente no tenemos el ancho de banda para embarcarnos en una reescritura de varios años de nuestro HTML y CSS junto con todos los temas que mantenemos, especialmente considerando que aún no hemos terminado el viaje de varios años de actualizaciones de Ember.

5 Me gusta