DiscourseのデフォルトSVGアイコンをテーマ内のカスタムアイコンに置き換える

Discourse のデフォルトの SVG アイコンは、テーマまたはテーマコンポーネント内で個別に、または全体をカスタム SVG に置き換えて上書きできます。こちらを参照してください。

ステップ 1 - SVG スプライトシートの作成

始めるには、SVG スプライトシートを作成する必要があります。これには、単一の追加のカスタム SVG アイコンから、何百もの完全な置き換えセットまで、あらゆるものを格納できます。

スプライトシートは SVG ファイルとして保存する必要があります。原則として、元の SVG アイコンファイルから <svg> タグの内容を <symbol> タグ内にネストし、それらに適切な識別子を付けます。

<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
  <symbol id="my-theme-icon-1">
    <!--
      ソース SVG アイコンファイルからの <svg> タグ内のコード
      これは通常、<svg> タグ間のすべてです
      (ただし、上記の <symbol> に置き換えられる SVG タグ自体は除く)
      ViewBox="0 0 0 0" などの属性はすべて <symbol> タグに転送できます
      -->
  </symbol>

  <symbol id="my-theme-icon-2">
    <!-- ここに SVG コード。必要に応じて <symbol> ブロックを追加します。
      -->
  </symbol>
</svg>
  • スプライトシート内の各シンボルにカスタム ID を追加するようにしてください。テーマ名をプレフィックスとして ID に付けると、わかりやすくなるでしょう(例: my-theme-icon)。

  • アイコンの色を既存のアイコンのように動的にするには、ハードコードされた色(#333 など)ではなく、currentColorfill を設定します。

  • アイコンのサイズ変更や正確な中央揃えを行うには、<symbol> タグに viewBox 属性を使用します。詳細については、How to Scale SVG | CSS-Tricks を参照してください。

  • SVG 内のスタイル競合に注意してください。たとえば、SVG には .st0{fill:#FF0000;} のようなインラインスタイルが定義されていることがよくあります。複数の SVG が同じクラスを使用している場合、問題が発生する可能性があります(これらの問題を修正するには、クラスを各アイコンに固有のものに変更します)。

  • アイコンが多い場合は、これを自動化する方法があります。https://www.npmjs.com/package/svg-sprite-generator は、SVG をスプライトシートに結合するための簡単なコマンドラインツールです。

例 - 単一のカスタムアイコンのスプライトシート

<?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>

ステップ 2 - スプライトシートをテーマに追加する

スプライトシートが作成されたら、SVG ファイルをコンポーネント/テーマに追加する必要があります。これは UI 経由で簡単に行うか、コンポーネント/テーマにハードコードすることができます。

:information_source: インストールされているコンポーネント/テーマのいずれかにアップロードされると、<symbol> タグ内の ID を使用してインスタンス全体で利用可能になります。

UI 経由

テーマ/コンポーネント設定のアップロードセクションに移動し、SCSS 変数名を icons-sprite としてスプライトファイルを追加します。

テーマ/コンポーネントへのハードコード

スプライトシートファイルをテーマの /assets フォルダーに追加します。次に、ルートフォルダーにある assets.json ファイルを更新します。
my-icons.svg という SVG スプライトの場合、about.json にはこれが含まれている必要があります。

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

ステップ 3 (オプション) - デフォルトアイコンの上書き

スプライトシートが設定されたので、Discourse にアイコンの置き換えを指示できます。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");
  // その他
});

最初の ID である bars は Discourse のデフォルトのアイコン ID であり、2 番目の ID は置き換えたいアイコンの ID です。Discourse のアイコンの ID を見つける最も簡単な方法は、ブラウザでそのアイコンを調べることです。

ここでは、アイコン名は d-icon- プレフィックスに従います。したがって、この例では d-unliked です。

ほとんどのアイコンは https://fontawesome.com/ のアイコン名に従いますが、例外もあります(そのため、インスペクタで ID を確認するのが最も信頼できる方法です)。例外はすべて、こちらの githubconst REPLACEMENTS ブロックで確認できます。

これで完了です。独自のカスタムアイコンで Discourse をスタイル設定できるようになりました!


このドキュメントはバージョン管理されています - 変更の提案はgithub で行えます。

「いいね!」 57

特定の要素内の特定のアイコンをどのようにターゲットにできますか?私の場合は、サイドバーメニューのドキュメントアイコンを別のFAアイコンに置き換えたいです。

CSSで非表示にして、新しいボタンを追加します。

Common / CSS

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

More > Customize this section で新しいボタンを追加します。

「いいね!」 3

これは機能しません。試してみたのは次のとおりです。

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

ここからですが、機能していないようです。プレビューリンクでこれが機能しないため、スクリプトタグの方法は壊れていると思います。正直よくわかりません。

私には機能します :woman_shrugging:t2:

ヘッドタブに入れていますか?ヘッダーのロボットも置き換えました。

管理者の SVG アイコンサブセット 設定にアイコンを追加する必要があるかもしれません。

「いいね!」 1

はい、ヘッドタブです。ガイドにそう書いてあるので、ヘッダータブでもあります。

完了しました。これで動作します。ありがとうございます!

「いいね!」 1

@NateDhaliwalさん、プライベートメッセージをいただけますか?何かお手伝いが必要なのですが、プロフィールにチャットオプションが見当たりません。ありがとうございます!

「いいね!」 1

左側のメニューでは、カテゴリ「Audi」内のプレフィックス-spanクラスを持つ要素の背景を再定義します */

.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;


メインページをクリックすると、正方形のアイコンが再び表示されます!何が間違っているのか教えていただけますか?カテゴリページ自体では機能します。

テーマ/コンポーネント名、ファイル名、SCSS変数名、シンボルIDの関係について、どなたか明確にしていただけますでしょうか?

モデレーターの shield-halved アイコンを自社のものに置き換えようとしていますが、手順が少し不明瞭です。

ステップ2では:

  • 「UI経由」(Replace Discourse's default SVG icons with custom icons in a theme icons-sprite のファイル名 baticonsprite.svg が表示されています。
  • しかし、「テーマにハードコードする」(Replace Discourse's default SVG icons with custom icons in a theme
    • しかし、どうすればよいのでしょうか?エディタに assets.json ファイルが見当たりません。コンポーネントをエクスポートすると、about.json が表示され、UI経由でアップロードしたスプライトが表示されます。
    • しかし、この例ではファイル名が /assets/my-icons.svg と異なっています。これは baticonsprite.svg と同じファイルのことでしょうか?
    • これら2つは同じことを行うための代替方法であり、両方ではなく、どちらか一方を行うだけでよいのでしょうか…?

ステップ3では:

  • しかし、api.replaceIcon() では、2番目のパラメータは、以前のID(icons-spritebat-iconbaticonsprite.svgmy-icons.svg のいずれでもありません)を使用していません。代わりに、まったく新しい my-theme-icon-bars が表示されます…混乱しています。
    • my-theme という接頭辞は必要ですか?もしそうなら、その「テーマ名」文字列はどこから来るのですか?例えば、my-theme-bat-icon となるべきでしょうか?テーマではなくコンポーネントの場合はどうなりますか?
    • そして、icon-bars の部分については、次のいずれかであるべきでしょうか?
      • SVGスプライトシートXMLのシンボルID
      • SVGファイルのファイル名
      • 指定したSCSS変数名
      • 上記のいずれかの組み合わせ(例:icons-sprite-bat-icon?)

そして、api.replaceIcon() の呼び出しはどこに配置すべきですか?カスタムコンポーネントの「JS」タブに配置しても問題ありませんか?そこにはすでに以下の定型文があります。

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

export default apiInitializer((api) => {
  // your code here
});

それとも、カスタム <script type=”discourse/plugin”> タグを作成し、それを <head> タブに配置する必要がありますか?


この件で混乱させてしまい申し訳ありません。

上記のいくつかの組み合わせを試しましたが、どんなに試してもスプライトが表示されませんでした…

私のスプライトXMLは次のようになっています。

<?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>

ファイル名は my-logo.svg で、SCSS変数名も my-logo です。

そして、カスタムコンポーネントの「JS」タブには次のコードがあります。

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

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

しかし、何も表示されません。何か手順が抜けているのでしょうか、それとも理解できていない魔法の文字列補間があるのでしょうか…?