Automatischer Dunkelmodus auch für eingebettete Kommentare?

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 „Gefällt mir“

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 „Gefällt mir“

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 „Gefällt mir“

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 „Gefällt mir“

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 „Gefällt mir“

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

11 „Gefällt mir“

Hallo,

Entschuldigen Sie, dass ich ein so altes Thema aufgreife, aber gibt es Pläne, den Dark-Mode-Automatikwechsel für eingebettete Kommentar-Endpunkte zu implementieren?

1 „Gefällt mir“

Wir haben derzeit keine Pläne, diese Funktion hinzuzufügen. Websites können Dark-Mode-Stile zu ihrem eingebetteten Stylesheet hinzufügen (als Workaround oder die oben diskutierte postMessage-Technik verwenden).

7 „Gefällt mir“

postMessage benötigt ein eingebettetes iframe, um das message-Ereignis zu verarbeiten.
Wo füge ich Code in ein iframe ein, um das Ereignis zu verarbeiten?

2 „Gefällt mir“

Ich habe es mit postMessage implementiert. Der Code und seine Ausführungslogik sind wie folgt:

Codeblock ① fügt einen Event-Listener in den eingebetteten Discourse-iframe ein, der eine Nachricht an meine Website sendet, die den eingebetteten Discourse-iframe enthält, sobald Discourse eingebettet ist.

Wenn meine Website eine Nachricht von eingebettetem Discourse empfängt, führt sie eine Validierung durch, wie in Codeblock ② gezeigt, und wenn diese erfolgreich ist, wird die Funktion setIframeStyle aufgerufen, um eingebettetes Discourse einzustellen.

Die Funktion setIframeStyle, die in Codeblock ③ gezeigt wird, übergibt den Farbmodus, „dark“ oder „light“, an den iframe, indem sie postMessage aufruft. Zusätzlich kann die Funktion aufgerufen werden, um den eingebetteten Discourse im gleichen Farbmodus wie meine Website zu halten, sobald der dunkle Modus umgeschaltet wird.

Codeblock ④ ermöglicht es eingebettetem Discourse, die von meiner Website gesendete Farbmodus-Nachricht zu verarbeiten. Hier schalte ich den Farbmodus um, indem ich den Klassennamen des Body-Tags ändere.

Zusätzlich werden Codeblock ① und ④ über die Discourse-Admin-Seite hinzugefügt, wie unten gezeigt:

Und benutzerdefinierte CSS-Klassen sollten wie folgt hinzugefügt werden:

12 „Gefällt mir“

Weiß jemand, wo man bearbeiten kann, wenn man "Eingebettetes CSS" nicht bearbeiten kann (weil kein offizielles Theme)?

2 „Gefällt mir“

Erstellen Sie gerade eine neue Komponente und verwenden Sie deren eingebetteten Tab?

3 „Gefällt mir“

Vielen Dank für den obigen Überblick, @mikeguo, das ist wunderbar erklärt!

Beachten Sie außerdem, dass Sie die neueste Discourse-Version verwenden müssen, um dies zu erreichen. Die Funktion für eingebettete Header wurde erst vor wenigen Tagen hinzugefügt.

8 „Gefällt mir“

EDIT: Das ist, was ich tun musste Structure of themes and theme components

Das scheint falsch zu sein?

const handleMessageListener = (event:MessageEvent<any>)

2 „Gefällt mir“

Ich kann diesen Code immer noch nicht aktivieren (!) Könnte ihn bitte jemand überarbeiten?

Ich sehe, dass niemand diesen aktivieren kann und fast jeder eine helle erzwungene Darstellung verwendet, das ist sehr schlecht für unsere Augen :frowning:

1 „Gefällt mir“

Ich kann bestätigen, dass die obige Methode immer noch funktioniert, aber es wäre schön gewesen, wenn ich den Code nicht von einem Screenshot hätte abtippen müssen :slight_smile: Hier ist er also, leicht aktualisiert:

Schritte

  1. Der Kommentare-Iframe ist gerendert und sendet eine Nachricht an das Haupt-Browserfenster, dass er fertig ist.
  2. Der Browser fragt seine Dunkel-/Hellmodus-Einstellung ab und sendet den Wert zurück in den Iframe.
  3. Der Iframe empfängt die Nachricht und setzt ein data-Attribut, eine Klasse oder Ähnliches basierend auf der Dunkel-/Hellmodus-Einstellung.

Code

  1. Sobald der Iframe geladen ist, senden Sie eine Benachrichtigung an das übergeordnete Fenster. Dies muss in Discourse unter Admin -> Anpassen -> (Thema auswählen) -> CSS/HTML bearbeiten -> Eingebetteter Header eingegeben werden.
<script type="text/javascript">
    window.addEventListener("load", (event) => {
        window.parent.postMessage("iframe loaded", "*");
    }, false);
</script>
  1. Behandeln Sie diesen eingehenden Trigger im Hauptfenster. Dieser Code befindet sich auf Ihrer Blog-Website:
<script type="text/javascript">
  const discourse_url = "https://your.discourse-instance.org";

  // Hier bestimmen wir das Thema und senden eine Nachricht an den Iframe, um ihn darüber zu informieren
  // Siehe unten, wie wir notifyFrameStyle einrichten
  const notifyIFrameOfTheme = () => {
    const iframe = document.getElementById("discourse-embed-frame");
    if (iframe && iframe.contentWindow) {
      iframe.contentWindow.postMessage(
        {
          // Ändern Sie die folgende Zeile, um die Dunkelmodus-Einstellung abzurufen, je nachdem, wie Sie sie speichern
          theme: document.documentElement.getAttribute("data-theme")
        },
        discourse_url
      );
    }
  };

  // Rufen Sie setFrameStyle auf, wenn wir die Nachricht "iframe loaded" erhalten
  const handleMessageListener = (event) => {
    var origin = event.origin;
    if ((origin === discourse_url) && (event.data == "iframe loaded")) {
      notifyIFrameOfTheme();
    }
  };
</script>
  1. Fügen Sie im script-Block aus (1) einen Listener für die vom notifyFrameStyle gesendete Thema-Nachricht hinzu:
    window.addEventListener("message", (event) => {
        const payload = event.data;
        if (payload.theme) {
          // Tun Sie etwas mit der Thema-Einstellung; ich setze das `data-theme`-Attribut auf dem `html`-Element des Iframes,
          // aber Sie möchten vielleicht ein class-Attribut oder Ähnliches setzen
          document.documentElement.setAttribute("data-theme", payload.theme);
        }
    }, false);

Styling

Unter Admin -> Anpassen -> (Thema auswählen) -> CSS/HTML bearbeiten -> Eingebettetes CSS können Sie nun CSS für jeden Modus bereitstellen. Sie können z. B. die Discourse-Styling-Variablen überschreiben:

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

Ich hoffe, das hilft!

6 „Gefällt mir“

Der obige kopierbare Code enthält die fehlende Hinzufügung des Event Listeners im Einbettungsfenster:

window.addEventListener("message", handleMessageListener);

Und ein Hinweis: Es sind keine speziellen CORS-Einstellungen erforderlich.

Danke, dass Sie das bemerkt haben! Ich kann den obigen Beitrag nicht mehr bearbeiten, aber window.addEventListener gehört am Ende des Code-Snippets unter (2).

Siehe dieses reale Beispiel.

5 „Gefällt mir“