Styliser Discourse avec des variables : un plaidoyer pour une sémantique plus simple

Continuant la discussion de Styling Discourse with variables: Show & Tell :

J’apprécie totalement les efforts déployés pour améliorer l’expérience de création de thèmes de Discourse ! Cependant, je ne suis pas entièrement convaincu que l’approche consistant à ajouter de nombreuses variables CSS, comme partagé dans le sujet ci-dessus, soit la solution optimale. Je voulais partager quelques réflexions à ce sujet.

J’ai moi-même expérimenté cette approche via le Canvas Theme Template, qui fournit essentiellement une collection de variables ajustables pour construire des thèmes de 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);

  /* Et plusieurs autres... */
}

Bien que cela fonctionne raisonnablement bien pour des ajustements simples, j’ai rencontré plusieurs limitations en essayant de faire évoluer cette approche :

Charge cognitive et découvrabilité

Une liste étendue de variables nécessite essentiellement une table de correspondance. Cela semble déconnecté de la façon dont on travaillerait typiquement dans un framework basé sur des composants, où l’on s’attendrait en fait à styliser des composants. Et peut-être que c’est juste moi, mais j’ai l’impression que cela déplace le modèle mental de « Je veux styliser ce composant » à « Je dois trouver le bon nom de variable ».

Manque de logique en cascade

L’implémentation actuelle attribue des valeurs codées en dur directement aux variables sans établir une hiérarchie de cascade appropriée :

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

Cela signifie qu’il n’y a pas d’héritage des variables plus générales comme --link-color ou --border-width. Si je veux apporter des changements systématiques, je dois mettre à jour plusieurs variables spécifiques au lieu de changer une valeur fondamentale.

Écart conception-développement

Je pense que l’approche crée des frictions lors du travail entre les outils de conception (comme Figma) et l’implémentation. Les systèmes de conception utilisent généralement des variables sémantiques qui ne correspondent pas un à un avec ces variables très spécifiques à l’implémentation.

Une approche alternative qui embrasse l’architecture des composants

Je pense que nous pourrions atteindre le même objectif plus naturellement en combinant des variables sémantiques de base avec un ciblage de composants fiable. Au lieu d’avoir une longue liste de variables spécifiques, que se passerait-il si nous pouvions compter sur des classes de composants uniques et nommées de manière cohérente dans tout Discourse ? Des choses comme .d-sidebar, .d-topic-list, .d-header.

Ensuite, associez cela à un ensemble plus restreint de variables fondamentales qui font réellement cascader les choses comme le CSS est censé fonctionner :

/* Définir les fondations du design */
:root {
  --d-border-width: 2px;
  --d-surface-color: #3498db;
  --d-space-1: 1rem;
}

/* Redéfinir au niveau du composant lorsque nécessaire */
.d-topic-list,
.d-sidebar {
  --d-border-width: 1px;
}

Pour moi, cela ressemble davantage à la façon dont le CSS fonctionne naturellement. Je définis mes styles globaux, puis je les affine si nécessaire. Quand je veux changer l’apparence des bordures dans toute l’application, je change une variable. Quand je veux que la barre latérale soit différente, je cible spécifiquement la barre latérale.

3 « J'aime »

Eh bien, je pense que la façon dont le CSS fonctionnerait naturellement serait simplement d’ignorer les variables et de faire

/* Définir les bases du design */
body {
  border-width: 2px;
  background-color: #3498db;
  margin: 1rem;
}

/* Surcharger au niveau du composant lorsque nécessaire */
.d-topic-list,
.d-sidebar {
  border-width: 1px;
}

Peut-être que je suis juste vieux.
Le vrai problème est ceci

Exemple : cibler simplement .btn ou button :

.btn {
    border: 1px solid red;
}

manque les boutons de publication mais cible le lien « vues » et le menu hamburger.

1 « J'aime »

Il y a de bonnes raisons d’utiliser des variables, peut-être ne nous y attardons pas ici. C’est un bon point cependant de ne pas débattre de la nature du CSS. J’aurais dû mieux formuler cela : il ne s’agit pas de sa nature, mais des meilleures pratiques pour styliser un framework basé sur des composants. Et je suis tout à fait d’accord que les boutons sont un autre bon exemple de la façon dont celles-ci ne peuvent pas être correctement appliquées.

En considérant la situation dans son ensemble, un effort concerté a été fait pour moderniser le côté JavaScript du framework frontend. Et je pense que ce fut un succès retentissant. Travailler avec des normes claires et des classes bien structurées est maintenant vraiment agréable. Pour moi, en tant que designer, cela a également ouvert des opportunités pour construire de nouveaux composants frontend plus facilement et plus efficacement.

Cependant, je n’arrive pas à me défaire de l’impression qu’il n’y a pas d’engagement similaire à amener le système de conception aux mêmes normes. Bien que l’ajout de variables CSS pour chaque aspect soit certainement plus performant et plus propre que l’approche actuelle, cela donne toujours l’impression d’éviter les problèmes architecturaux plus profonds : une base de code pleine de déclarations trop spécifiques et sans styles clairs limités aux composants. Cela ressemble à une solution « plus facile » qui évite le problème plus difficile : aligner pleinement l’architecture de style avec la conception modulaire du framework.

Je comprends que cela entraînerait beaucoup de travail et des problèmes de compatibilité ascendante. Mais l’équipe a relevé ces défis avec succès du côté JavaScript. Si JavaScript continue de recevoir beaucoup plus de ressources que les styles, cette disparité se reflétera dans les conceptions finales. Et les utilisateurs ressentiront la différence, même s’ils ne peuvent pas l’articuler.

J’aimerais simplement voir la même énergie de modernisation appliquée à l’architecture CSS, car je suis convaincu que les avantages à long terme pour l’expérience développeur et utilisateur seraient transformateurs.

5 « J'aime »

L’approche que nous avons adoptée semble aller dans le sens de ce que vous décrivez, j’ai donc du mal à comprendre comment vous l’auriez mise en œuvre différemment. Je suis cependant tout à fait ouvert aux commentaires et j’apprécie la perspective que vous apportez.

Par exemple, pour quelque chose comme --space, changer cela modifierait tout l’espacement dans l’application. Vous pourriez également cibler cela pour n’affecter que l’espacement dans la liste de sujets ou la barre latérale avec des approches similaires à celles que vous avez décrites.

C’est vrai pour certains éléments, mais pas pour d’autres. D’autres exemples que vous pourriez partager seraient les bienvenus !

C’est certainement un problème. Une approche que nous avons en tête (du moins expérimentalement pour l’instant) est un éditeur dans la lignée de ce que fait shadcn ici :

Bien que ce ne soit pas une approche parfaite, je pense qu’elle nous rapprocherait de la simplification pour les personnes qui ne savent pas utiliser l’inspecteur / accéder aux métadonnées pour la documentation / utiliser le CSS.

En ce qui concerne une approche plus basée sur les composants, c’est quelque chose que nous voulons éventuellement réaliser, mais Discourse tel qu’il existe n’a pas été conçu dans une optique de conception par composants, et attendre d’y parvenir avant d’ajouter des variables utilisables n’était pas une option.

L’ajout de certaines classes pour faciliter la mise en œuvre dans certaines sections semble être une bonne voie à suivre en termes d’utilisabilité.


Je suis d’accord avec vous :+1:

2 « J'aime »

La réponse courte est : ne faites pas ça :sweat_smile:

Il est beaucoup plus judicieux de cibler une classe de bouton secondaire, btn-default, btn-primary, btn-flat — ces classes secondaires représentent un type visuel de bouton.

.btn et button sont plus largement « c’est un bouton » plutôt que toute apparence spécifique.

4 « J'aime »

C’est exactement ce que c’est. Nous n’avons actuellement pas la bande passante nécessaire pour entreprendre une réécriture de plusieurs années de notre HTML et CSS ainsi que de tous les thèmes que nous maintenons, surtout que nous ne sommes pas encore terminés avec le parcours de plusieurs années des mises à jour d’Ember.

5 « J'aime »