埋め込みコメントにも自動ダークモードですか?

Automatic Dark Mode color scheme switching は素晴らしい機能追加で、これを統合していただきありがとうございます!

(自動)色テーマの切り替えが可能になった今、ブログに埋め込まれたコメントでも、Discourse のライトモードとダークモードを行き来して切り替える方法はないかと考えています。具体的には、私の Ghost ブログには、ユーザーがクリックして手動でライトモードとダークモードを切り替えられるトグルがあります。ブログの CSS では Discourse の iframe 内の CSS に影響を与えられないことは承知していますが、この新機能により、そのトグルで Discourse の色テーマも切り替えられる別の方法はないでしょうか?コメント付きの投稿の例は、こちらの投稿 の下部でご確認いただけます。

「いいね!」 11

これは理論的には可能ですが、少し複雑です。現時点では、埋め込みコメントエンドポイントにダークモードの自動切り替え機能は追加されていません。これを追加することはできますが、ブラウザがダークモードに切り替わった際にあなたの Ghost サイトも自動的にダークモードに切り替わる場合に限って機能します。しかし、あなたの Ghost サイトはダークモード切り替えボタンを使用しているようです。これは Discourse の実装では機能しません。

あなたの具体的なケースでは、ボタンをクリックした際に Discourse の埋め込みコメント iframe 内のクラスを切り替え、そのクラスを使って埋め込みスタイルシート内の色を切り替えることができます。

「いいね!」 13

なるほど。現在、同僚のためにいくつかのダークモード対応の(Ghost)テーマを作成中ですが、これらすべてが単一の Discourse インスタンスを共有することになります。ただ、それはもう少し先の話です。

残念ながら、ここで提案されていることがよく理解できません。現在、私のブログ内でダークモードのスタイルを利用したい要素は、それらの前に body.dark を付けて CSS を重複して定義しています。具体的には以下の通りです。

p {
    color: #000;
}
body.dark p {
    color: #FFF;
}

Discourse の iframe 内の要素を変更するために、その body.dark コードを使用することを提案されているのでしょうか?私は Discourse の「埋め込み CSS」フィールドに以下のコードを挿入してみましたが、残念ながら効果はありませんでした。

.FF2F-discourse p {
    color: #000;
}
body.dark .FF2F-discourse p {
    color: #FFF;
}

もしそうではない場合、トグル操作が iframe 内の特定のクラスをターゲットにして別の変更を引き起こすように、何らかの個別の JavaScript を記述することを提案されているのでしょうか?先ほどコメントした通り、外部のコードが iframe 内の CSS に影響を与えることはできないと思っていたため、混乱しています。しかし、私は HTML/CSS の素人ですので、あなたが私よりも詳しいことはもちろん、私が何かを誤解している可能性も十分にあります。

ヒントをいただきありがとうございます。

「いいね!」 7

はい、それが私の提案です。あなたのブログのスタイルシートは iframe に適用できませんが、JS を使って iframe の html または body 要素で dark クラスを切り替え、それに応じて Discourse 埋め込みスタイルシートを更新することができます。

「いいね!」 11

Discourse の埋め込み機能でライトモードとダークモードを切り替える方法について説明しているページを 2 つ見つけましたが、私の JavaScript を担当している方が、あなたが提案している方法が postMessage(私が探したページに記載されているもの)を使うのか、それとも別の手法なのかを確認したいと考えています。

以下は、postMessage を使ったウィンドウ間通信の実装方法について説明しているページです。

一方、このページは実際に postMessage を使って iframe 内の CSS を変更する方法、特にライトモードとダークモードの切り替えに特化したチュートリアルです。

https://cobwwweb.com/change-css-iframe

私のアプローチはこれで正しいでしょうか?

「いいね!」 8

申し訳ありません、ここへの返信を忘れていました。はい、postMessage があなたのユースケースに適用できると思います。

「いいね!」 11

こんにちは。

大変古いトピックを掘り起こしてしまい申し訳ありませんが、埋め込みコメントエンドポイントへのダークモードの自動切り替えを実装する予定はありますか?

「いいね!」 1

現在、この機能を追加する予定はありません。サイトでは、回避策として埋め込みスタイルシートにダークモードのスタイルを追加できます(または、上記で説明した postMessage テクニックを使用できます)。

「いいね!」 7

postMessagemessage イベントを処理するために埋め込み iframe を必要とします。
イベントを処理するために iframe にコードを追加するにはどうすればよいですか?

「いいね!」 2

postMessage を使用して実装しました。コードとその実行ロジックは以下のとおりです。

コードブロック①は、埋め込まれたDiscourse iframe内でイベントリスナーを追加します。これにより、埋め込まれたDiscourseがロードされると、Discourse iframeを埋め込んでいる私のウェブサイトにメッセージが投稿されます。

私のウェブサイトが埋め込まれたDiscourseからのメッセージを受信すると、コードブロック②に示すように検証を行い、合格した場合は setIframeStyle 関数を呼び出して埋め込まれたDiscourseのスタイルを設定します。

コードブロック③に示す setIframeStyle 関数は、postMessage を呼び出すことによって、カラーモード(「dark」または「light」)をiframeに渡します。さらに、ダークモードが切り替わった後、この関数を呼び出すことで、埋め込まれたDiscourseを私のウェブサイトと同じカラーモードに保つことができます。

コードブロック④は、埋め込まれたDiscourseが私のウェブサイトから送信されたカラーモードメッセージを処理できるようにします。ここでは、bodyタグのクラス名を切り替えることでカラーモードを切り替えます。

さらに、コードブロック①と④は、以下のようにDiscourse管理ページに追加されます。

カスタムCSSクラスは以下のように追加する必要があります。

「いいね!」 12

「埋め込みCSS」を編集できない場合(公式テーマではないため)、どこを編集すればよいかご存知の方はいらっしゃいますか?

「いいね!」 2

新しいコンポーネントを作成し、その埋め込みタブを使用しますか?

「いいね!」 3

上記の概要をありがとうございます @mikeguo、素晴らしい説明です!

また、これを実現するには最新の Discourse を使用する必要があることに注意してください。埋め込みヘッダー機能は数日前に追加されたばかりです。

「いいね!」 8

「編集:」それは私がしなければならなかったことです Structure of themes and theme components

それは間違っているようですか?

const handleMessageListener = (event:MessageEvent<any>)

「いいね!」 2

このコードを有効にできません (!) どなたか、親切に確認していただけますか?

誰もこれを有効にできず、ほとんどの人がライト強制を使用しているのを見かけますが、それは私たちの目に非常に悪いです :frowning:

「いいね!」 1

上記の方法で確認できましたが、スクリーンショットからコードを入力しなければならなかったのは残念です :slight_smile: 以下に、少し更新したものを記載します。

手順

  1. コメントのiframeのレンダリングが完了し、メインのブラウザウィンドウにその旨を伝えるメッセージを送信します。
  2. ブラウザは、ダーク/ライトモードの設定を照会し、その値をiframeに返します。
  3. iframeはメッセージを受信し、ダーク/ライトモードの設定に基づいてdata-attribute、classなどを設定します。

コード

  1. iframeが読み込まれたら、親ウィンドウに通知を送信します。これは、Discourse管理者 -> カスタマイズ -> (テーマを選択) -> CSS/HTMLの編集 -> 埋め込みヘッダー に入力する必要があります。
    window.addEventListener("load", (event) => {
        window.parent.postMessage("iframe loaded", "*");
    }, false);
  1. メインウィンドウでこの受信したトリガーを処理します。このコードはブログサイトに配置します。
  const discourse_url = "https://your.discourse-instance.org";

  // ここでテーマを決定し、テーマが何であるかをiframeに知らせるメッセージを送信します
  // notifyFrameStyle を設定する方法については、以下を参照してください
  const notifyIFrameOfTheme = () => {
    const iframe = document.getElementById("discourse-embed-frame");
    if (iframe && iframe.contentWindow) {
      iframe.contentWindow.postMessage(
        {
          // ダークモードの設定をどのように保存しているかに応じて、以下の行をダークモード設定を取得するように変更してください
          theme: document.documentElement.getAttribute("data-theme")
        },
        discourse_url
      );
    }
  };

  // "iframe loaded" メッセージを受信したときに setFrameStyle を呼び出します
  const handleMessageListener = (event) => {
    var origin = event.origin;
    if ((origin === discourse_url) && (event.data == "iframe loaded")) {
      notifyIFrameOfTheme();
    }
  };
  1. (1) の script ブロックで、notifyFrameStyle によって送信されたテーマメッセージのリスナーを追加します。
    window.addEventListener("message", (event) => {
        const payload = event.data;
        if (payload.theme) {
          // テーマ設定で何かを行う。私はiframeの `html` に `data-theme` 属性を設定しましたが、
          // class属性などを設定したい場合もあります
          document.documentElement.setAttribute("data-theme", payload.theme);
        }
    }, false);

スタイリング

管理者 -> カスタマイズ -> (テーマを選択) -> CSS/HTMLの編集 -> 埋め込みCSS で、各モードのCSSを提供できるようになります。例えば、Discourseのスタイリング変数をオーバーライドできます。

html[data-theme="dark"] {
  --primary: #ced6dd;
  --primary-low: #48566b;
  --secondary: #14181e;
  --tertiary: #2b7e8d;
}

お役に立てれば幸いです!

「いいね!」 6

上記のコピー&ペースト可能なコードには、埋め込みウィンドウでのイベントリスナーの追加が欠けています。

window.addEventListener("message", handleMessageListener);

注意点:これには特別なCORS設定は必要ありません。

指摘ありがとうございます!上記の投稿はもう編集できませんが、window.addEventListener は (2) のコードスニペットの下部に追加します。

実際の例をご覧ください。

「いいね!」 6