[Prueba A/B] Cambio de la clase CSS padre según la variable del experimento

Tenemos un tema existente que queremos experimentar. Un ejemplo sería probar diferentes estilos de vista de la lista de temas. Para esto, estamos utilizando pruebas A/B de Google Optimize. Actualmente, planeamos mostrar el tema sin cambios al 50% de los usuarios y el resto con el tema actualizado. El original y la variante deben definirse en el mismo tema, ya que vamos a experimentar con una pequeña parte. El problema es que las clases CSS padre comparten el mismo nombre y queremos aplicar estilos a esas clases padre según una variable específica. ¿Cómo podemos aplicar estilos separados a diferentes plantillas si comparten el mismo nombre de clase padre?

A continuación, se presenta un escenario simplificado de lo que estamos intentando lograr.

Considere que tengo un tema donde el estilo de la lista de temas está definido así en common/common.scss:

.topic-list {
  tbody {
    border: none;
  }
  tr {
    border: none;
  }
  .example-div {
    border: none;
  }
}

Y en mi variante, quiero configurarlo así:

.topic-list {
  tbody {
    display: block;
    tr {
      display: block;
    }
  }
  .example-div {
    border: 2px solid black;
  }
  .another-example-div { 
    font-size: 10px;
  }
}

Los archivos Handlebars que se están sobrescribiendo se ven así:

javascripts/discourse/templates/list/custom-topic-list-item.hbr

<div class='example-div'>
  Hola
</div>

javascripts/discourse/templates/list/variant-custom-topic-list-item.hbr

<div class='example-div'>
  Hola,
  <div class='another-example-div'>
    Encantado de conocerte
  </div>
</div>

El nombre de clase topic-list se menciona en el componente de Discourse, pero la estructura después de la renderización es así:

<table class="topic-list">
  <tr class="topic-list-item">
   <div class='example-div'>
      Hola
    </div>
  </tr>
</table>

Quiero renderizar uno de estos archivos dependiendo del ID de usuario en mi archivo de encabezado:
common/header.html

const { findRawTemplate } = require("discourse-common/lib/raw-templates");
const user_id = api.getCurrentUser().id
 
api.modifyClass('component:topic-list-item', {
  renderTopicListItem() {
    let template = findRawTemplate("list/custom-topic-list-item");
    if (user_id % 2 === 0)
       template = findRawTemplate("list/variant-custom-topic-list-item");
    if (template) {
      this.set("topicListItemContents", template(this).htmlSafe());
    }
  },
});

Gracias.

Ten en cuenta que esto probablemente está causando un error no capturado en los usuarios que no han iniciado sesión. Recomiendo cambiarlo por:

const user = api.getCurrentUser();
if (!user) return;

const userId = user.id;

Con esto aclarado, volvamos a tu pregunta.

A diferencia de CSS, SCSS admite un selector de padre, por lo que puedes usar esa característica.

Dado que quieres aplicar esto a cada segundo usuario (id % 2),

puedes verificarlo cuando se carga la aplicación. Algo así, justo al principio:

const user = api.getCurrentUser();
const userId = user.id;

if (!userId) return;

const testThemeUser = userId % 2 === 0;

if (testThemeUser) {
  document.body.classList.add("test-theme");
}

Luego puedes usar testThemeUser en tus condicionales de JS y la clase CSS test-theme en tus estilos.

Así que algo como esto.

JS

let template = findRawTemplate("list/custom-topic-list-item");
if (testThemeUser)
  template = findRawTemplate("list/variant-custom-topic-list-item");
if (template) {
  this.set("topicListItemContents", template(this).htmlSafe());
}

SCSS

.topic-list {
  tbody {
    border: none;
  }
  tr {
    border: none;
  }
  .example-div {
    border: none;
  }
  // estilos del tema de prueba
  .test-theme & {
    .example-div {
      border: 2px solid black;
    }
    .another-example-div {
      font-size: 10px;
    }
  }
}

Gracias por tu respuesta @Johani
Actualmente solo necesito actualizar una clase de componente específica, que es topic-list, por lo que estoy utilizando este enfoque:

const useTestTheme = userId % 2 === 0

api.modifyClass('component:topic-list', {
    classNameBindings: ["test"],
    test: useTestTheme,
})