Sostituire le icone SVG predefinite di Discourse con icone personalizzate in un tema

È possibile sostituire le icone SVG predefinite di Discourse singolarmente o tutte insieme con le proprie icone SVG personalizzate e sovrascriverle all’interno di un tema o di un componente tema.

Passaggio 1 - Creare un foglio di sprite SVG

Per iniziare, è necessario creare un foglio di sprite SVG. Questo può contenere qualsiasi cosa, da una singola icona SVG personalizzata aggiuntiva a un’intera serie di sostituzione di centinaia di icone.

Il foglio di sprite deve essere salvato come file SVG. In linea di principio, si annidano i contenuti del tag <svg> dal file icona SVG originale all’interno di tag <symbol> e si assegna loro un bell’identificatore.

<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
  <symbol id="my-theme-icon-1">
    <!--
      Codice all'interno del tag <svg> dal file icona SVG di origine
      questo è tipicamente tutto ciò che si trova tra i tag <svg>
      (ma non il tag SVG stesso, che è sostituito da <symbol> sopra)
      È possibile trasferire qualsiasi attributo (ad esempio ViewBox="0 0 0 0") al tag <symbol>
      -->
  </symbol>

  <symbol id="my-theme-icon-2">
    <!-- Codice SVG qui. Aggiungere altri blocchi <symbol> se necessario.
      -->
  </symbol>
</svg>
  • Assicurati di aggiungere un ID personalizzato a ogni simbolo nel foglio di sprite. Probabilmente è utile per la tua sanità mentale anteporre il nome del tuo tema agli ID, ad esempio my-theme-icon.

  • Per far sì che il colore dell’icona sia dinamico come le icone esistenti, imposta il riempimento su currentColor anziché su un colore fisso (come #333)

  • Per scalare o centrare correttamente l’icona, utilizza un attributo viewBox sul tag <symbol>. Consulta How to Scale SVG | CSS-Tricks per maggiori informazioni.

  • Fai attenzione alle collisioni di stile all’interno dei tuoi SVG. Ad esempio, gli SVG spesso hanno uno stile inline come .st0{fill:#FF0000;} definito. Se hai più SVG che utilizzano le stesse classi, ciò può causare problemi (per risolvere questi problemi, modifica le classi in modo che siano univoche per ogni icona).

  • Se hai molte icone, ci sono modi per automatizzare questo processo. https://www.npmjs.com/package/svg-sprite-generator è un semplice strumento da riga di comando per combinare SVG in un foglio di sprite.

Esempio - foglio di sprite con icona personalizzata singola

<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
  <symbol id="bat-icon" viewBox="6 6 36 36">
    <path
      fill="currentColor"
      d="M24,18.2c0.7,0,0.9,0.2,0.9,0.2l0.4-1.7c0,0,0.4,1.5,0.4,2.8c0.2,1.1,2.2,0.4,3.9,0C31.4,19.1,32,16,32,16h16c0,0-9.4,3.5-7,10c0,0-14.8-2-17,7l0,0c-2.2-9-17-7-17-7c2.4-6.5-7-10-7-10h16c0,0,0.6,3.1,2.3,3.5c1.7,0.4,3.9,1.1,3.9,0c0.2-1.1,0.4-2.8,0.4-2.8l0.4,1.7C23.1,18.4,23.4,18.2,24,18.2L24,18.2L24,18.2z"
    />
  </symbol>
</svg>

Passaggio 2 - Aggiungere il foglio di sprite al tema

Una volta creato il foglio di sprite, è necessario aggiungere il file SVG al componente/tema. Questo è facile tramite l’interfaccia utente, oppure è possibile codificarlo direttamente in un componente/tema.

:information_source: Una volta caricato in qualsiasi componente/tema installato, è disponibile in tutta l’istanza utilizzando l’ID nel tag <symbol>.

Tramite l’interfaccia utente

Vai alla sezione Uploads delle impostazioni del tema/componente e aggiungi il tuo file sprite con un nome di variabile SCSS di icons-sprite:

Codifica diretta in un Tema / Componente

Aggiungi il file del foglio di sprite alla cartella /assets del tema. Quindi aggiorna il file assets.json nella cartella radice.
Per un file SVG sprite chiamato my-icons.svg, il tuo about.json dovrebbe includere questo:

"assets": {
  "icons-sprite": "/assets/my-icons.svg"
}

Passaggio 3 (facoltativo) - Sovrascrivere le icone predefinite

Ora che il foglio di sprite è impostato, puoi dire a Discourse di sostituire le icone. Ecco come farlo da un api-initializer:

// {theme}/javascripts/discourse/api-initializers/init-theme.gjs

import { apiInitializer } from "discourse/lib/api";

export default apiInitializer((api) => {
  api.replaceIcon("bars", "my-theme-icon-bars");
  api.replaceIcon("link", "my-theme-icon-link");
  // ecc.
});

Il primo ID, bars, è l’ID icona predefinito in Discourse e il secondo è l’ID della tua icona di sostituzione. Il modo più semplice per trovare l’ID di una delle nostre icone è ispezionare l’icona nel browser.

Qui il nome dell’icona segue il prefisso d-icon-. Quindi in questo esempio è d-unliked

La maggior parte delle nostre icone segue i nomi delle icone da https://fontawesome.com/, ma ci sono eccezioni (motivo per cui controllare l’ID nell’ispettore è il metodo più affidabile). È possibile visualizzare tutte le eccezioni nel blocco const REPLACEMENTS qui su github.

Questo è tutto. Ora puoi stilizzare Discourse con le tue icone personalizzate!


Questo documento è controllato in versione - suggerisci modifiche su github.

57 Mi Piace

Come si potrebbe selezionare un’icona specifica in un elemento specifico? Nel mio caso, vorrei sostituire l’icona Docs nel menu della barra laterale con un’altra icona FA.

Lo nasconderei con CSS e aggiungerei un nuovo pulsante per esso.

Common / CSS

.sidebar-section-wrapper {
  li[data-list-item-name=docs] {
    display: none !important;
  }
}

Aggiungi un nuovo pulsante in Altro > Personalizza questa sezione

3 Mi Piace

Questo non funziona. Ho provato a fare un:

<script type="text/discourse-plugin" version="0.8">
    api.replaceIcon("shield-halved", "hat-wizard");
</script>

da qui, ma non sembra funzionare. Penso che il metodo del tag script sia rotto, dato che questo non funziona con il link di anteprima. Onestamente non sono sicuro.

funziona per me :woman_shrugging:t2:

lo stai inserendo nella scheda head? ho anche sostituito il robot nel mio header:

potrebbe essere necessario aggiungere l’icona all’impostazione SVG icon subset dell’admin.

1 Mi Piace

[citazione=“Lilly, post:40, topic:115736”]
lo stai mettendo nella scheda head?
[/citazione]

Sì, nella scheda head. E nella scheda header, dato che lo dice la guida.

[citazione=“Lilly, post:40, topic:115736”]
SVG icon subset
[/citazione]
Fatto. Ora funziona. Grazie!

1 Mi Piace

@NateDhaliwal Potresti mandarmi un messaggio privato per favore? Ho bisogno di aiuto con qualcosa e non vedo l’opzione chat nel tuo profilo. Grazie!

1 Mi Piace
Per il menu di sinistra, ridefiniamo lo sfondo dell'elemento con la classe prefix-span all'interno della categoria Audi */
.navigation-category [data-category-id="6"] .prefix-span {
  background: url("https://raw.githubusercontent.com/tima4502/car-icons/bb0d0fae3e5b66c512a27a130b219ec0ee342ada/audi.svg") center/contain no-repeat !important;

quando clicco sulla pagina principale l’icona quadrata appare di nuovo! puoi dirmi cosa sto sbagliando? e sulla pagina della categoria stessa funziona

Ciao, qualcuno potrebbe per favore chiarire la relazione tra un nome di tema/componente, nome del file, nome della variabile SCSS e l’ID del simbolo…?

Sto cercando di sostituire l’icona del moderatore shield-halved con una nostra, ma le istruzioni sono un po’ poco chiare.

Nel passaggio 2:

  • Lo screenshot “Tramite l’interfaccia utente” mostra un nome di file baticonsprite.svg con un nome di variabile SCSS icons-sprite
  • Ma poi in “Codifica manuale in un tema”, ti dice di codificarlo manualmente in un tema/componente
  • Ma come? Non vedo un file assets.json nell’editor. Se esporto il componente, vedo un about.json, che mostra lo sprite che ho caricato tramite l’interfaccia utente
  • Ma questo esempio mostra anche un nome di file diverso /assets/my-icons.svg — è inteso come lo stesso file di baticonsprite.svg?
  • Questi sono due modi alternativi per fare la stessa cosa, e devi farne solo uno OPPURE l’altro, non entrambi…?

Nel passaggio 3:

  • Ma poi ora, in api.replaceIcon(), il secondo parametro non utilizza nessuno degli ID precedenti, né icons-spritebat-iconbaticonsprite.svgmy-icons.svg. Invece, otteniamo un my-theme-icon-bars completamente nuovo… confuso.
  • È richiesto il prefisso my-theme, e se sì, da dove proviene questa stringa “nome del tema”? Come se dovesse essere my-theme-bat-icon? E se è un componente, non un tema?
  • E per la parte icon-bars, dovrebbe essere:
  • L’ID del simbolo dal file XML dello sprite SVG
  • Il nome del file SVG
  • Il nome della variabile SCSS che gli dai
  • Una combinazione di quanto sopra (come icons-sprite-bat-icon?)

E dove metti effettivamente la chiamata api.replaceIcon()? Va bene metterla nella scheda “JS” di un componente personalizzato, che ha già il boilerplate:

import { apiInitializer } from "discourse/lib/api";

export default apiInitializer((api) => {
  // il tuo codice qui
});

O è necessario creare un tag personalizzato <script type=”discourse/plugin”> e metterlo invece nella scheda <head>?


Scusa per la mia confusione qui.

Ho provato diverse combinazioni di quanto sopra e non sono riuscito a far apparire il mio sprite in nessun modo…

Il mio sprite XML assomiglia a:

<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">


<symbol id="my-logo" viewBox="0 0 94.652 95.261"><defs><linearGradient id="a" y1="47.631" x2="94.652" y2="47.631" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#ff593d"/><stop offset="1" stop-color="#ff7751"/></linearGradient></defs><title>d_only</title><path d="M47.326,0H0V95.261H47.326c23.67,0,47.326-21.326,47.326-47.624S71,0,47.326,0Zm0,69.274a21.644,21.644,0,1,1,21.65-21.637A21.635,21.635,0,0,1,47.326,69.274Z" fill="url(#a)"/></symbol>

</svg>

Il nome del file è my-logo.svg e anche il nome della variabile SCSS è my-logo

E nella scheda JS del componente personalizzato, ho:

import { apiInitializer } from "discourse/lib/api";

export default apiInitializer((api) => {
    api.replaceIcon("shield-halved", "my-logo")
});

Ma non sembra apparire nulla. Manca un passaggio, o c’è un qualche tipo di interpolazione di stringa magica che non sto capendo…?