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

Automatic Dark Mode color scheme switching is a fantastic addition, thanks for integrating it!

With (automatic) color scheme switching available, I’m wondering if there might also be some way to switch back and forth between light and dark Discourse modes when embedded as comments in a blog. Specifically, my Ghost blog has a toggle that users can click on to manually switch back and forth between light and dark modes. I know that my blog’s CSS can’t effect the CSS within Discourse’s iframe, but with this new addition might there be another way that the toggle could also switch the Discourse color scheme? You can see an example post with comments at the bottom of this post.

「いいね!」 11

This is potentially doable but a little tricky. At the moment, we haven’t added dark mode auto switching to the embedded comments endpoint. We can add that, and it would work if your Ghost site was auto-switching to dark mode when the browser switches to dark mode. But from what I can tell, your Ghost site uses a dark mode button, which won’t work with the Discourse implementation.

What you can do in your specific case, is toggle a class in the Discourse embedded comments iframe when clicking the button, and then use that class to toggle colors in your embedded stylesheet.

「いいね!」 13

Sounds good. While I am currently putting together several dark mode utilizing (Ghost) themes for colleagues of mine, all of which will share a single Discourse instance, that’s still a bit further down the road.

I unfortunately don’t quite understand what you’re suggesting here. Currently, any elements that I want to utilize dark mode styling within my blog have their CSS doubled up by preceding such items with body.dark. As in

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

Might you be suggesting that I use that body.dark code to change things in the Discourse iframe? Because I tried inserting the following into Discourse’s Embedded CSS field, which unfortunately had no effect:

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

That being so, are you instead suggesting that I have some separate JS written so that the toggle will affect a separate change via specific targeting of a class in the iframe? Because like I stated in my previous comment, I didn’t think that external coding could affect CSS within an iframe, hence my confusion. But I’m very much solely an HTML/CSS amateur, so there’s no doubt that you know better than me and/or that I’m misunderstanding something else.

Thanks again for any hints.

「いいね!」 6

Yes, that’s what I am suggesting. Your blog’s stylesheets cannot apply to the iframe, but you can use JS to toggle the dark class in the iframe’s html or body element, and then update your Discourse embedded stylesheet accordingly.

「いいね!」 10

I’ve found two pages explaining how toggling between light and dark modes for Discourse’s embed might be done, but the guy who writes my JS is wondering if the method you’re suggesting entails using postMessage (which the pages I found state) or something else.

Here’s a page explaining how to implement cross-window messaging with postMessage

While this one is actually a tutorial on how to change the CSS within an iframe via postMessage, specifically for switching between light and dark modes:

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

Might I be on the right track with all this?

「いいね!」 8

My apologies, I forgot to respond here, yes, I think postMessage can work for your use case.

「いいね!」 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) のコードスニペットの下部に追加します。

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

「いいね!」 5