¿Modo oscuro automático también para los comentarios embebidos?

Automatic Dark Mode color scheme switching es una adición fantástica, ¡gracias por integrarla!

Con la posibilidad de cambiar (automáticamente) el esquema de colores, me pregunto si también podría existir alguna forma de alternar entre los modos claro y oscuro de Discourse cuando se incrusta como comentarios en un blog. En concreto, mi blog de Ghost tiene un interruptor que los usuarios pueden hacer clic para cambiar manualmente entre los modos claro y oscuro. Sé que el CSS de mi blog no puede afectar al CSS dentro del iframe de Discourse, pero con esta nueva adición, ¿podría existir otra forma de que el interruptor también cambie el esquema de colores de Discourse? Puedes ver un ejemplo de publicación con comentarios al final de esta publicación.

11 Me gusta

Esto es potencialmente factible, pero un poco complicado. Por el momento, no hemos añadido el cambio automático a modo oscuro al punto final de comentarios incrustados. Podríamos añadirlo, y funcionaría si tu sitio de Ghost cambiara automáticamente a modo oscuro cuando el navegador lo hace. Pero, por lo que puedo ver, tu sitio de Ghost utiliza un botón para el modo oscuro, lo cual no funcionará con la implementación de Discourse.

Lo que puedes hacer en tu caso específico es alternar una clase en el iframe de comentarios incrustados de Discourse al hacer clic en el botón y, a continuación, usar esa clase para alternar los colores en tu hoja de estilos incrustada.

13 Me gusta

Suena bien. Actualmente estoy preparando varios temas (Ghost) que utilizan el modo oscuro para mis colegas, todos los cuales compartirán una única instancia de Discourse, pero eso todavía está un poco más adelante.

Por desgracia, no termino de entender qué estás sugiriendo aquí. Actualmente, cualquier elemento que quiera que utilice estilos de modo oscuro dentro de mi blog tiene su CSS duplicado precediendo dichos elementos con body.dark. Es decir:

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

¿Estás sugiriendo que use ese código body.dark para cambiar cosas en el iframe de Discourse? Porque intenté insertar lo siguiente en el campo CSS Incrustado de Discourse, lo cual, por desgracia, no tuvo ningún efecto:

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

Dado esto, ¿estás sugiriendo en su lugar que escriba algún JavaScript separado para que el botón alterne un cambio específico mediante la selección de una clase en el iframe? Porque, como mencioné en mi comentario anterior, no creía que el código externo pudiera afectar al CSS dentro de un iframe, de ahí mi confusión. Pero soy únicamente un aficionado a HTML/CSS, así que sin duda sabes más que yo y/o estoy malinterpretando algo más.

Gracias de nuevo por cualquier pista.

7 Me gusta

Sí, eso es lo que estoy sugiriendo. Las hojas de estilo de tu blog no pueden aplicarse al iframe, pero puedes usar JS para alternar la clase dark en el elemento html o body del iframe y, a continuación, actualizar tu hoja de estilo incrustada de Discourse en consecuencia.

11 Me gusta

He encontrado dos páginas que explican cómo se podría realizar el cambio entre los modos claro y oscuro para la incrustación de Discourse, pero la persona que escribe mi código JS se pregunta si el método que sugieres implica el uso de postMessage (como indican las páginas que encontré) o algo distinto.

Aquí hay una página que explica cómo implementar la comunicación entre ventanas con postMessage:

Mientras que esta otra es en realidad un tutorial sobre cómo cambiar el CSS dentro de un iframe mediante postMessage, específicamente para alternar entre los modos claro y oscuro:

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

¿Estoy en el buen camino con todo esto?

8 Me gusta

Mis disculpas, olvidé responder aquí. Sí, creo que postMessage puede funcionar para tu caso de uso.

11 Me gusta

Hola,

Lamento reabrir un tema tan antiguo, pero ¿hay planes para implementar el cambio automático al modo oscuro en el endpoint de comentarios incrustados?

1 me gusta

Actualmente no tenemos planes de añadir esta función. Los sitios pueden añadir estilos de modo oscuro a su hoja de estilos incrustada como solución alternativa (o utilizar la técnica postMessage comentada anteriormente).

7 Me gusta

postMessage necesita un iframe incrustado para manejar el evento message.
¿Dónde agrego código a un iframe para manejar el evento?

2 Me gusta

Lo he implementado usando postMessage. Los códigos y su lógica de ejecución son los siguientes:

El bloque de código ① agrega un detector de eventos en el iframe de Discourse incrustado que enviará un mensaje a mi sitio web que contiene el iframe de Discourse incrustado una vez que Discourse incrustado se cargue.

Cuando mi sitio web reciba el mensaje de Discourse incrustado, realizará una validación, como se muestra en el bloque de código ②, y si pasa, llamará a la función setIframeStyle para configurar Discourse incrustado.

La función setIframeStyle, que se muestra en el bloque de código ③, pasa el modo de color, “oscuro” o “claro”, al iframe llamando a postMessage. Además, una vez que se cambie el modo oscuro, la función se puede llamar para mantener Discourse incrustado con el mismo modo de color que mi sitio web.

El bloque de código ④ permite que Discourse incrustado pueda procesar el mensaje del modo de color enviado desde mi sitio web. Aquí cambio el modo de color cambiando el nombre de la clase a la etiqueta del cuerpo.

Además, los bloques de código ① y ④ se agregan a través de la página de administración de Discourse, como se muestra a continuación:

Y las clases CSS personalizadas deben agregarse de la siguiente manera:

12 Me gusta

¿Alguien sabe dónde editar si no podemos editar “CSS incrustado” (porque no es un tema oficial)?

2 Me gusta

¿Acabas de crear un nuevo componente y usar su pestaña Incrustado?

3 Me gusta

¡Gracias por el esquema anterior @mikeguo, está maravillosamente explicado!

Además, ten en cuenta que necesitas tener la última versión de Discourse para lograr esto, la capacidad de Encabezado Embebido se agregó hace solo unos días.

8 Me gusta

EDITAR: Eso es lo que necesito hacer Structure of themes and theme components

¿Eso parece estar mal?

const handleMessageListener = (event:MessageEvent<any>)

2 Me gusta

Todavía no puedo habilitar este código (!). ¿Alguien podría, por favor, revisarlo amablemente?

Veo que nadie puede habilitar esto y casi todos usan la luz forzada, lo que es muy malo para nuestros ojos :frowning:

1 me gusta

Confirmo que el método anterior todavía funciona, pero habría sido bueno no tener que escribir código de una captura de pantalla :slight_smile: Así que, aquí está, ligeramente actualizado:

Pasos

  1. El iframe de comentarios termina de renderizarse y envía un mensaje a la ventana principal del navegador, informándole.
  2. El navegador consulta su configuración de modo oscuro/claro y envía el valor de vuelta al iframe.
  3. El iframe recibe el mensaje y establece un atributo de datos, una clase o similar, basándose en la configuración de modo oscuro/claro.

Código

  1. Una vez que el iframe se carga, envía una notificación a la ventana principal. Esto debe introducirse en Discourse, en Admin -> Personalizar -> (seleccionar tema) -> Editar CSS/HTML -> Encabezado incrustado.
    window.addEventListener("load", (event) => {
        window.parent.postMessage("iframe loaded", "*");
    }, false);
  1. Maneja este disparador entrante en la ventana principal. Este código vive en tu sitio de blog:
  const discourse_url = "https://your.discourse-instance.org";

  // Aquí, determinamos el tema y enviamos un mensaje al iframe para que sepa cuál es el tema
  // Ver más abajo cómo conectamos notifyFrameStyle
  const notifyIFrameOfTheme = () => {
    const iframe = document.getElementById("discourse-embed-frame");
    if (iframe && iframe.contentWindow) {
      iframe.contentWindow.postMessage(
        {
          // Modifica la línea de abajo para obtener la configuración del modo oscuro, dependiendo de cómo la almacenes
          theme: document.documentElement.getAttribute("data-theme")
        },
        discourse_url
      );
    }
  };

  // Llama a setFrameStyle cuando recibimos el mensaje "iframe loaded"
  const handleMessageListener = (event) => {
    var origin = event.origin;
    if ((origin === discourse_url) && (event.data == "iframe loaded")) {
      notifyIFrameOfTheme();
    }
  };
  1. En el bloque <script> de (1), añade un listener para el mensaje del tema enviado por notifyFrameStyle:
    window.addEventListener("message", (event) => {
        const payload = event.data;
        if (payload.theme) {
          // Haz algo con la configuración del tema; establecí el atributo `data-theme` en el `<html>` del iframe,
          // pero es posible que desees establecer un atributo de clase o similar
          document.documentElement.setAttribute("data-theme", payload.theme);
        }
    }, false);

Estilo

En Admin -> Personalizar -> (seleccionar tema) -> Editar CSS/HTML -> CSS incrustado, ahora puedes proporcionar CSS para cada modo. Por ejemplo, puedes anular las variables de estilo de Discourse:

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

¡Espero que eso ayude!

6 Me gusta

El código copiable y pegable anterior omite la adición del detector de eventos en la ventana de incrustación:

window.addEventListener("message", handleMessageListener);

Y una nota: No se necesitan configuraciones especiales de CORS para esto.

¡Gracias por darte cuenta! Ya no puedo editar la publicación anterior, pero window.addEventListener va al final del fragmento de código debajo del (2).

Consulta este ejemplo del mundo real.

6 Me gusta