Styling Discourse con variabili: un caso per una semantica più semplice

Continuando la discussione da Styling Discourse with variables: Show & Tell:

Apprezzo molto lo sforzo per migliorare l’esperienza di theming di Discourse! Tuttavia, non sono del tutto convinto che l’approccio di aggiungere molte variabili CSS come condiviso nell’argomento sopra sia la soluzione ottimale. Volevo condividere alcuni pensieri sul perché.

Ho sperimentato io stesso questo approccio attraverso il Canvas Theme Template, che fornisce essenzialmente una raccolta di variabili regolabili per la creazione di temi di 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);

  /* E molte altre... */
}

Sebbene questo funzioni ragionevolmente bene per aggiustamenti semplici, ho riscontrato diverse limitazioni nel tentativo di scalare questo approccio:

Sovraccarico cognitivo e scopribilità

Un elenco esteso di variabili richiede essenzialmente una tabella di ricerca. Questo sembra scollegato da come si lavorerebbe tipicamente in un framework basato su componenti, dove ci si aspetterebbe di stilizzare i componenti. E forse sono solo io, ma sento che sposta il modello mentale da “Voglio stilizzare questo componente” a “Devo trovare il nome della variabile giusta”.

Mancanza di logica a cascata

L’implementazione attuale assegna valori hardcoded direttamente alle variabili senza stabilire una corretta gerarchia a cascata:

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

Ciò significa che non c’è ereditarietà da variabili più generali come --link-color o --border-width. Se voglio apportare modifiche sistematiche, devo aggiornare più variabili specifiche invece di cambiare un valore fondamentale.

Divario design-sviluppo

Penso che l’approccio crei attrito quando si lavora tra strumenti di design (come Figma) e l’implementazione. I sistemi di design utilizzano tipicamente variabili semantiche che non si mappano uno a uno con queste variabili molto specifiche dell’implementazione.

Un approccio alternativo che abbraccia l’architettura dei componenti

Penso che potremmo raggiungere lo stesso obiettivo in modo più naturale combinando variabili semantiche di base con un targeting affidabile dei componenti. Invece di avere un lungo elenco di variabili specifiche, cosa succederebbe se potessimo contare su classi di componenti uniche e nominate in modo coerente in tutto Discourse? Cose come .d-sidebar, .d-topic-list, .d-header.

Quindi, abbinalo a un set più piccolo di variabili fondamentali che effettivamente si propagano nel modo in cui il CSS è destinato a funzionare:

/* Imposta le fondamenta del design */
:root {
  --d-border-width: 2px;
  --d-surface-color: #3498db;
  --d-space-1: 1rem;
}

/* Sovrascrivi a livello di componente quando necessario */
.d-topic-list,
.d-sidebar {
  --d-border-width: 1px;
}

Per me, questo assomiglia di più a come funziona naturalmente il CSS. Imposto i miei stili globali, poi li perfeziono dove necessario. Quando voglio cambiare l’aspetto dei bordi in tutta l’app, cambio una variabile. Quando voglio che la barra laterale sia diversa, seleziono specificamente la barra laterale.

3 Mi Piace

Beh, penso che il modo in cui il CSS funzionerebbe naturalmente sia semplicemente saltare le variabili e fare

/* Imposta le basi del design */
body {
  border-width: 2px;
  background-color: #3498db;
  margin: 1rem;
}

/* Sovrascrivi a livello di componente quando necessario */
.d-topic-list,
.d-sidebar {
  border-width: 1px;
}

Forse sono solo vecchio.

Il vero problema è questo

Esempio: puntare semplicemente a .btn o button:

.btn {
    border: 1px solid red;
}

perde i pulsanti dei post ma punta al link “visualizzazioni” e al menu hamburger.

1 Mi Piace

Ci sono valide ragioni per usare le variabili, forse non entriamo nei dettagli qui. È un buon punto, però, non discutere sulla natura del CSS. Avrei dovuto formularla meglio: non si tratta della sua natura, ma delle best practice per lo styling di un framework basato su componenti. E sono completamente d’accordo sul fatto che i pulsanti siano un altro buon esempio di come queste non possano essere applicate correttamente.

Guardando al quadro generale, c’è stato uno sforzo concertato per modernizzare il lato JavaScript del framework frontend. E penso che sia stato un successo clamoroso. Lavorare con standard puliti e classi ben strutturate è ora veramente piacevole. Per me, come designer, ha anche aperto opportunità per costruire nuovi componenti frontend in modo più facile ed efficiente.

Tuttavia, non riesco a liberarmi dalla sensazione che non ci sia un impegno simile nel portare il design system allo stesso livello. Sebbene l’aggiunta di variabili CSS per ogni aspetto sia certamente più performante e pulita dell’approccio attuale, sembra ancora un modo per evitare i problemi architettonici più profondi: una codebase piena di dichiarazioni eccessivamente specifiche e senza stili chiari limitati ai componenti. Questo sembra una soluzione “più facile” che evita il problema più difficile: allineare completamente l’architettura di styling con il design modulare del framework.

Capisco che ciò comporterebbe molto lavoro e problemi di compatibilità con le versioni precedenti. Ma il team ha affrontato queste sfide con successo sul lato JavaScript. Se JavaScript continuerà a ricevere risorse significativamente maggiori rispetto agli stili, tale disparità si rifletterà nei design finali. E gli utenti sentiranno la differenza, anche se non riescono a spiegare perché.

Mi piacerebbe semplicemente vedere la stessa energia di modernizzazione applicata all’architettura CSS perché sono convinto che i benefici a lungo termine sia per l’esperienza dello sviluppatore che per quella dell’utente sarebbero trasformativi.

5 Mi Piace

L’approccio che abbiamo adottato sembra essere in linea con ciò che stai descrivendo, quindi ho difficoltà a capire come li avresti implementati diversamente. Sono decisamente aperto a feedback e apprezzo la prospettiva che stai portando.

Ad esempio, per qualcosa come --space, cambiarlo modificherebbe tutti gli spazi nell’app. Potresti anche limitarlo ad influenzare solo gli spazi nella topic-list o nella sidebar con approcci simili a quelli che hai descritto.

Questo è vero per alcuni elementi, ma non per altri. Qualsiasi altro esempio che potresti condividere sarebbe fantastico!

Questo è sicuramente un problema. Un approccio che abbiamo in mente (almeno per ora in via sperimentale) è un editor simile a quello che shadcn sta facendo qui:

Anche se non è un approccio perfetto, credo che ci avvicinerebbe a rendere le cose più facili per le persone che non sanno come usare l’ispettore / accedere ai metadati per la documentazione / usare il CSS.

Per quanto riguarda un approccio più basato sui componenti, è qualcosa che vogliamo raggiungere in futuro, ma Discourse, così com’è, non è stato costruito tenendo conto della progettazione componentizzata, e aspettare di arrivarci prima di aggiungere variabili utilizzabili non era un’opzione.

Aggiungere alcune classi per rendere più facile l’implementazione in determinate sezioni sembra un buon percorso per migliorare l’usabilità.


Sono d’accordo con te :+1:

2 Mi Piace

La risposta breve è non farlo :sweat_smile:

È molto meglio puntare a una classe di pulsante secondaria, btn-default, btn-primary, btn-flat — queste classi secondarie rappresentano un tipo visivo di pulsante.

.btn e button sono più in generale “questo è un pulsante” piuttosto che un aspetto specifico.

4 Mi Piace

È esattamente così. Al momento non abbiamo la larghezza di banda per intraprendere una riscrittura pluriennale del nostro HTML e CSS insieme a ogni tema che manteniamo, soprattutto considerando che non abbiamo ancora terminato il percorso pluriennale degli aggiornamenti di Ember.

5 Mi Piace