Modalità scura automatica anche per i commenti incorporati?

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 Mi Piace

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 Mi Piace

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 Mi Piace

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 Mi Piace

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 Mi Piace

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

11 Mi Piace

Ciao,

Mi scuso per aver riesumato un argomento così datato, ma ci sono piani per implementare il cambio automatico della modalità scura per l’endpoint dei commenti incorporati?

1 Mi Piace

Al momento non abbiamo in programma di aggiungere questa funzionalità. I siti possono aggiungere stili in modalità scura al loro foglio di stile incorporato come soluzione alternativa (o utilizzare la tecnica postMessage discussa in precedenza).

7 Mi Piace

postMessage necessita di un iframe incorporato per gestire l’evento message.
Dove aggiungo il codice a un iframe per gestire l’evento?

2 Mi Piace

L’ho implementato utilizzando postMessage. Il codice e la sua logica di esecuzione sono i seguenti:

Il blocco di codice ① aggiunge un listener di eventi nell’iframe Discourse incorporato che invierà un messaggio al mio sito web che contiene l’iframe Discourse incorporato una volta che Discourse incorporato sarà caricato.

Quando il mio sito web riceve un messaggio da Discourse incorporato, effettuerà una validazione, come mostrato nel blocco di codice ②, e se superata, chiamerà la funzione setIframeStyle per impostare Discourse incorporato.

La funzione setIframeStyle, mostrata nel blocco di codice ③, passa la modalità colore, “dark” o “light”, all’iframe chiamando postMessage. Inoltre, una volta attivata la modalità scura, la funzione può essere chiamata per mantenere Discourse incorporato con la stessa modalità colore del mio sito web.

Il blocco di codice ④ consente a Discourse incorporato di elaborare il messaggio della modalità colore inviato dal mio sito web. Qui cambio la modalità colore cambiando il nome della classe nel tag body.

Inoltre, i blocchi di codice ① e ④ sono aggiunti dalla pagina di amministrazione di Discourse, come segue:

E le classi CSS personalizzate dovrebbero essere aggiunte come segue:

12 Mi Piace

Qualcuno sa dove modificare se non possiamo modificare il "CSS incorporato" (perché non è un tema ufficiale)?

2 Mi Piace

Hai appena creato un nuovo componente e utilizzi la sua scheda Incorporato?

3 Mi Piace

Grazie per la panoramica sopra @mikeguo, è spiegata meravigliosamente!

Nota anche che devi essere sull’ultima versione di Discourse per realizzare questo, la funzionalità Embedded Header è stata aggiunta solo pochi giorni fa.

8 Mi Piace

MODIFICA: Era quello che dovevo fare Structure of themes and theme components

Sembra sbagliato?

const handleMessageListener = (event:MessageEvent<any>)

2 Mi Piace

Non riesco ancora ad abilitare questo codice (!) Qualcuno potrebbe per favore, gentilmente rivederlo?

Vedo che nessuno può abilitarlo e quasi tutti usano la luce forzata, il che è molto dannoso per i nostri occhi :frowning:

1 Mi Piace

Posso confermare che il metodo sopra funziona ancora, ma sarebbe stato bello non dover digitare il codice da uno screenshot :slight_smile: Quindi, eccolo qui, leggermente aggiornato:

Passaggi

  1. L’iframe dei commenti finisce di renderizzarsi e invia un messaggio alla finestra principale del browser, informandola.
  2. Il browser interroga la sua impostazione di modalità scura/chiara e invia il valore indietro nell’iframe.
  3. L’iframe riceve il messaggio e imposta un attributo data, una classe o simile, in base all’impostazione della modalità scura/chiara.

Codice

  1. Una volta caricato l’iframe, invia una notifica alla finestra padre. Questo deve essere inserito su Discourse, sotto Admin -> Personalizza -> (seleziona tema) -> Modifica CSS/HTML -> Intestazione incorporata.
    <script type="text/javascript">
        window.addEventListener("load", (event) => {
            window.parent.postMessage("iframe loaded", "*");
        }, false);
    </script>
  1. Gestisci questo trigger in arrivo nella finestra principale. Questo codice si trova sul tuo sito blog:
    <script type="text/javascript">
      const discourse_url = "https://your.discourse-instance.org";

      // Qui, determiniamo il tema e inviamo un messaggio all'iframe per informarlo del tema
      // Vedi sotto come impostiamo notifyFrameStyle
      const notifyIFrameOfTheme = () => {
        const iframe = document.getElementById("discourse-embed-frame");
        if (iframe && iframe.contentWindow) {
          iframe.contentWindow.postMessage(
            {
              // Modifica la riga sottostante per recuperare l'impostazione della modalità scura, a seconda di come la memorizzi
              theme: document.documentElement.getAttribute("data-theme")
            },
            discourse_url
          );
        }
      };

      // Chiama setFrameStyle quando riceviamo il messaggio "iframe loaded"
      const handleMessageListener = (event) => {
        var origin = event.origin;
        if ((origin === discourse_url) && (event.data == "iframe loaded")) {
          notifyIFrameOfTheme();
        }
      };
    </script>
  1. Nel blocco <script> da (1), aggiungi un listener per il messaggio del tema inviato da notifyFrameStyle:
    window.addEventListener("message", (event) => {
        const payload = event.data;
        if (payload.theme) {
          // Fai qualcosa con l'impostazione del tema; ho impostato l'attributo `data-theme` sull' `<html>` dell'iframe,
          // ma potresti voler impostare un attributo di classe o simile
          document.documentElement.setAttribute("data-theme", payload.theme);
        }
    }, false);

Stile

Sotto Admin -> Personalizza -> (seleziona tema) -> Modifica CSS/HTML -> CSS incorporato, puoi ora fornire CSS per ogni modalità. Ad esempio, puoi sovrascrivere le variabili di stile di Discourse:

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

Spero che questo aiuti!

6 Mi Piace

Il codice copiabile/incollabile sopra non include l’aggiunta dell’event listener nella finestra di incorporamento:

window.addEventListener("message", handleMessageListener);

E una nota: non sono necessarie impostazioni CORS speciali per questo.

Grazie per avermelo fatto notare! Non posso più modificare il post qui sopra, ma window.addEventListener va in fondo allo snippet di codice sotto il punto (2).

Vedi questo esempio reale.

5 Mi Piace