Discourse Lightbox - Migration hors de Magnific popup

Discourse permet aux utilisateurs de télécharger des images dans les messages (et ailleurs). Parfois, ces images sont trop grandes pour être affichées directement, aussi Discourse crée une version mise à l’échelle de l’image et l’ajoute au message. Lorsque vous cliquez sur cette image mise à l’échelle, une superposition élégante s’affiche contenant l’image en taille réelle : c’est ce qu’on appelle couramment le « lightboxing ».

Actuellement, Discourse utilise une bibliothèque appelée Magnific Popup pour gérer le comportement du lightboxing. Ce sujet traite de la refonte des lightboxes dans Discourse en migrant de Magnific Popup vers une solution plus en phase avec les attentes actuelles des utilisateurs et des développeurs.

Le pourquoi

Magnific est une excellente bibliothèque, et le nombre d’étoiles sur sa page du projet indique clairement combien de problèmes elle a résolus pour les utilisateurs et les développeurs au fil des ans.

Elle était également en avance sur son temps en termes de facilité d’utilisation et de fonctionnalités proposées. Cela devient évident lorsque l’on considère que presque toutes les fonctionnalités que vous voyez aujourd’hui étaient déjà présentes dans la version 1.0, sortie en 2014.

Alors, où en sommes-nous ? Je vais faire court. Magnific Popup a été conçu pour un monde entièrement différent où la compatibilité entre navigateurs était bien loin de ce qu’elle est aujourd’hui. Cela signifie quatre choses :

  1. elle dépend de jQuery
  2. elle contient du code destiné à d’anciens navigateurs
  3. le dispositif moyen utilisé pour accéder au web a beaucoup changé depuis
  4. elle a été conçue avec autre chose que les applications monopages (SPA) comme Discourse comme priorité, à savoir des pages statiques. Cela soulève des problèmes de performance spécifiques aux applications monopages, auxquels nous reviendrons plus tard.

Compte tenu de l’état actuel des standards web et de la manière dont vous pouvez réaliser toutes sortes de magie avec du JavaScript pur (vanilla), il est compréhensible que de grands projets comme Discourse s’éloignent de la dépendance à jQuery. Notez que les discussions sur jQuery sont hors sujet ici ; ceci n’est donné que pour le contexte.

Donc, voici le pourquoi : moins de jQuery, moins de code pour d’anciens navigateurs, de meilleures performances globales et un meilleur support pour le dispositif moyen – aujourd’hui très différent.

Le comment

Il n’y a pas de pénurie de solutions proposées, et on pourrait débattre de la nécessité de ne pas réinventer la roue, mais… n’allons pas là-dedans et restons concis.

Peut-être que le moyen le plus court de traiter ce point sensible est de dire… peu importe à quel point une solution « prête à l’emploi » peut bien convenir… elle ne s’intégrera jamais aussi parfaitement qu’une solution sur mesure, et laissons-en là.

Il y a pas mal de choses à considérer ici, que ce soit la surcharge de fonctionnalités avec des bibliothèques couvrant de nombreux cas d’usage comme les images, les iframes, les vidéos, etc., ou le manque de clarté autour des licences.

Connaître les cas d’usage spécifiques que Discourse doit prendre en charge permet d’éviter le code inutile, ce qui permet d’ajouter des fonctionnalités ciblées sans se retrouver avec beaucoup de surcharge.

Nous avons donc maintenant une base solide. Les exigences sont :

  1. pas de jQuery
  2. se concentrer uniquement sur les images pour l’instant
  3. prise en charge d’améliorations de qualité de vie comme le balayage sur mobile
  4. intégration avec Discourse pour permettre une personnalisation/amélioration ultérieure via les systèmes actuels de thèmes et de plugins.

Le quoi

Discourse est un projet basé sur Ember, donc la nouvelle lightbox doit être un composant Ember pour gérer le balisage et les données. De plus, comme il est attendu que vous puissiez configurer des lightboxes n’importe où dans l’application, disposer d’un service lightbox a beaucoup de sens. Cela permettra aux développeurs de :

  1. injecter le service dans n’importe quel composant et lier les méthodes de configuration/nettoyage du service au cycle de vie du composant
  2. rechercher le service n’importe où dans l’application et appeler ses méthodes de configuration/nettoyage

De plus, dans une optique d’amélioration de la qualité de vie, nous pouvons ajouter un peu d’abstraction et créer quelques fonctions utilitaires utilisables dans les thèmes. Nous y reviendrons plus tard.

Puisque l’un des objectifs est de permettre aux thèmes et plugins d’étendre la fonctionnalité, le service lightbox communiquera les changements d’état via des événements d’application (appEvents). Il émettra les événements suivants :

  • lightbox:opened
  • lightbox:item-will-change
  • lightbox:item-did-change
  • lightbox:closed

Chaque événement sera déclenché avec le type de données que les développeurs attendent généralement. Par exemple, l’événement lightbox:opened contiendra une liste de tous les éléments et l’élément actuel sur lequel la lightbox s’est ouverte. Nous y reviendrons plus tard.

Ceci étant dit, passons à la suite.

Ces dernières semaines, j’ai travaillé sur une proposition de PR introduisant Discourse Lightbox.

À première vue, elle peut sembler un peu volumineuse, alors décomposons-la.

Tester quelque chose qui repose sur beaucoup d’interactions utilisateur est délicat, c’est pourquoi la suite de tests de la lightbox comprend 63 tests avec 291 assertions.

Une fois la taille des tests abordée, faisons une rapide comparaison de taille avec Magnific Popup (tous deux non minifiés) :

Discourse Lightbox LOC Magnific Popup LOC Différence
JavaScript 1197 1860 (35 %)
CSS 813 351 131 %
Templates 401 0 -
Total 2411 2211 9,1 %

Ainsi, Discourse Lightbox contient environ 9 % de code en plus que Magnific. Bien sûr, ce n’est qu’une partie de l’histoire pour deux raisons :

  1. Nous n’avons pas pris en compte jQuery, dont dépend Magnific. jQuery 3.6 représente environ 11 k LOC.
  2. Discourse Lightbox ajoute plus de fonctionnalités par rapport à Magnific.

Entrons dans le détail de ces fonctionnalités.

Tout effet de saccade (« jank ») visible dans les vidéos ci-dessous est lié à l’enregistrement, et non à ce que les utilisateurs vivront. Toutes les animations/transitions s’exécuteront à un taux solide de 60 FPS.

Alors, sans plus tarder,

Mise en page de base

vidéo de la mise en page de base de la nouvelle Discourse Lightbox proposée | vidéo

Pour comparaison, voici la même chose avec l’implémentation actuelle de Magnific :

vidéo de la mise en page de base de la Discourse Lightbox actuelle | vidéo

Quelques points concernant les vidéos ci-dessus :

  1. La nouvelle lightbox utilisera l’image comme arrière-plan (backdrop) au lieu d’un fond sombre semi-transparent générique. L’image, par définition, se complétera elle-même. Notez que cela n’ajoute aucune surcharge réseau. L’image utilisée pour l’arrière-plan est celle du corps du message, ce qui signifie qu’elle aura déjà été mise en cache lorsque les utilisateurs ouvriront la lightbox.

  2. Discourse Lightbox opte pour une interface utilisateur fixe. Au lieu d’avoir le bouton de fermeture, le titre et les métadonnées de l’image attachés à l’image, ils disposent de leurs propres espaces réservés. Cela aidera à réduire les sauts (« jumpiness ») lors de la navigation entre des images de dimensions différentes.

  3. La navigation entre les images peut se faire avec les flèches dans la lightbox ou via des raccourcis clavier. ou pour suivant, et ou pour précédent. Sur les locales RTL, les raccourcis sont inversés en conséquence.

La mise en page sur mobile est très similaire, sauf que les flèches ne sont pas affichées car des gestes de balayage (swipe) sont ajoutés pour la navigation.

vidéo de la mise en page de base de la Discourse Lightbox proposée sur mobile | vidéo

Balayez vers la gauche sur mobile pour suivant, et vers la droite pour précédent. Sur les locales RTL, les gestes de balayage sont inversés.

Zoom

La nouvelle lightbox dispose d’un bouton de zoom dédié visible lorsque l’image que vous consultez est plus grande que les dimensions de la fenêtre d’affichage (viewport). Cliquer sur le bouton de zoom agrandit l’image, et cliquer à nouveau sur le bouton la réduit. De plus, un raccourci clavier pour zoomer/dézoomer est désormais disponible : Z. Enfin, si l’image est zoomable, cliquer dessus aura le même effet.

Voici une vidéo démontrant les trois méthodes :

vidéo démontrant les 3 méthodes de zoom dans la nouvelle lightbox | vidéo

Notez que bien que non démontré dans la vidéo ci-dessus, le curseur, lorsque vous survolez une image zoomable, changera pour le refléter. Il changera également en une icône zoom-out lorsque vous survolerez une image déjà zoomée.

Le zoom fonctionne différemment dans la nouvelle lightbox. Sur ordinateur de bureau, la section zoomée de l’image suivra le curseur.

video-2023-01-11_10.01.33 | vidéo

Il n’y a pas de survol sur mobile ; il utilise le défilement tactile classique pour se déplacer dans une image zoomée.

video-2023-01-11_09.40.57 | vidéo

Rotation

La nouvelle lightbox ajoute un bouton de rotation dédié pour tourner l’image par incréments de 90 degrés. La rotation dispose également d’un raccourci clavier : la touche R. Voici à quoi cela ressemble :

video-2023-01-11_10.07.35 | vidéo

La rotation et le zoom peuvent être combinés.

Mode plein écran

La nouvelle lightbox ajoute un bouton plein écran. Ce bouton fera entrer la fenêtre du navigateur en mode plein écran. Le raccourci clavier est M.

video-2023-01-11_10.13.58 | vidéo

Il gardera une trace de son état et reviendra au mode normal lorsque le plein écran sera désactivé ou lorsque la lightbox sera fermée.

Téléchargement

La lightbox actuelle ajoute un lien « télécharger » sous l’image. La nouvelle lightbox fait de même, mais remplace ce lien par une icône et l’ajoute au pied de page (footer) de la lightbox. Elle respecte toujours les mêmes permissions. Si…

prevent_anons_from_downloading_images

est activé et que l’utilisateur n’est pas connecté, l’icône de téléchargement ne sera pas affichée.

Nouvel onglet

La lightbox actuelle ajoute un lien « original » sous l’image qui l’ouvre dans un nouvel onglet. La nouvelle lightbox fait de même, mais l’ajoute sous forme d’icône dans l’en-tête de la lightbox. Elle respectera également le même paramètre de permission que l’icône de téléchargement.

Titre de l’image

La nouvelle lightbox se concentre principalement sur l’image. Les titres d’images sont tronqués à une ligne par défaut, mais prennent en charge l’expansion. Voici un exemple de ce à quoi cela ressemble :

video-2023-01-11_10.29.55 | vidéo

Il existe un raccourci clavier pour étendre/réduire le titre : T, et le titre ne sera pas affiché lorsque l’image est zoomée ou tournée.

Carrousel

Une nouvelle fonctionnalité disponible consiste à afficher toutes les images de la galerie dans un carrousel. La mise en page dépendra de l’écran de l’appareil ; elle peut être horizontale ou verticale. Voici à quoi cela ressemble :

video-2023-01-11_10.39.22 | vidéo

Il existe un raccourci clavier pour activer/désactiver le carrousel : A.

Et voici à quoi cela ressemble sur mobile :

video-2023-01-11_10.43.48 | vidéo

Balayer vers le bas sur mobile activera/désactivera le carrousel.

Fermeture

La touche Échap fonctionne toujours comme avant sur ordinateur de bureau pour fermer la lightbox. Il existe désormais un geste de balayage supplémentaire sur mobile : vous pouvez balayer vers le haut pour fermer la lightbox.

Accessibilité

Au-delà des bases comme les libellés des boutons, la nouvelle lightbox ajoute un élément d’annonce pour les lecteurs d’écran hors écran. Lorsque vous naviguez vers une image à l’intérieur de la lightbox, elle lira son index et son titre selon le format suivant :

image %{current} sur %{total} : %{title}

Voici un court exemple :

video-2023-01-11_11.20.42 | vidéo

La nouvelle lightbox supprime également tous les boutons inutiles qui ne servent à rien pour les lecteurs d’écran via aria-hidden.

Rappelez-vous que l’accessibilité est une mission en cours et que ceci est loin d’être terminé. Il y a toujours quelque chose à améliorer, mais je me suis arrêté ici pour garder les choses simples pour la version 1.

Ceci couvre toutes les fonctionnalités de la nouvelle lightbox.

Passons maintenant à un peu de langage technique pour développeurs.

Écouteurs d’événements (Event-listeners)

La lightbox actuelle ajoute des écouteurs d’événements de clic à chaque image de lightbox individuelle dans les messages cuits (« cooked posts »). Cela signifie qu’un message avec 20 images aura 20 écouteurs d’événements de clic pour les lightboxes.

La nouvelle lightbox utilise la délégation d’événements et n’ajoute qu’un seul écouteur d’événement au message lui-même.

Voici le nombre d’écouteurs d’événements pour la lightbox actuelle sur un message avec 20 images, pour un utilisateur anonyme dans une fenêtre de navigation privée, après avoir forcé la collecte de déchets (garbage collection) :

Et voici le même message avec la nouvelle lightbox :

De plus, la navigation à l’intérieur de la lightbox ajoute actuellement des écouteurs d’événements qui finissent par devenir orphelins et interfèrent ainsi avec la collecte de déchets. Voici un graphique de :

  1. Charger une page de sujet avec un message contenant 20 images.
  2. Ouvrir la lightbox et naviguer à travers les 20 images trois fois de suite.
  3. Fermer la lightbox.
  4. Forcer la collecte de déchets du navigateur.

Lightbox actuelle :

Nouvelle lightbox :

En ce qui concerne les écouteurs d’événements sur les lightboxes elles-mêmes, ceux-ci ne semblent pas être nettoyés actuellement dans Magnific (rappelez-vous, il n’a pas été conçu pour les applications monopages).

Une petite note sur les tests ci-dessus : ils sont très rudimentaires et les chiffres ne sont pas censés être « scientifiques » ; l’objectif ici est de déterminer la direction, pas les chiffres exacts.

Notes pour les développeurs

Parlons de la configuration et du nettoyage des lightboxes avec la nouvelle Discourse Lightbox.

Configuration et nettoyage des lightboxes

Les développeurs ont deux options.

  1. Injecter le service lightbox dans un composant via :

    import { inject as service } from "@ember/service";
    
    //...
    
    @service lightbox
    

    Vous pouvez ensuite appeler :

    this.lightbox.setupLightboxes({
      container: yourContainer // nœud DOM
      selector: ".css-selector" // sélecteur de chaîne pour les éléments que vous voulez mettre en lightbox
    })
    

    Puis, chaque fois que vous voulez nettoyer, il suffit d’appeler :

    this.lightbox.cleanupLightboxes()

    C’est tout.

  2. Si vous ne voulez pas injecter le service lightbox, vous pouvez importer setupLightboxes et cleanupLightboxes comme ceci :

    import {
      cleanupLightboxes,
      setupLightboxes,
    } from "discourse/lib/lightbox";
    

    Le reste est le même que pour l’injection du service. Ces deux fonctions rechercheront le service pour vous. Donc :

    setupLightboxes({
     container: yourContainer // nœud DOM
     selector: ".css-selector" // sélecteur de chaîne pour les éléments que vous voulez mettre en lightbox
    })
    
    //....
    
    cleanupLightboxes()
    

Notez que les deux appels, que ce soit directement depuis le service ou via les fonctions utilitaires, accepteront également une liste de nœuds (nodeList) pour la compatibilité ascendante, mais cela n’est pas recommandé.

Une dernière note à ce sujet : vous pouvez également faire en sorte qu’un élément non-image agisse comme déclencheur pour ouvrir une lightbox que vous avez configurée. Par exemple :

<div class="my-container">
  <img class="my-selector" src="foo">
  <img class="my-selector" src="bar">
  ....
  <button>Ouvrir la lightbox</button>
</div>

Je ferais quelque chose comme ceci pour configurer des lightboxes de base sur le div ci-dessus :

import {
  cleanupLightboxes,
  setupLightboxes,
} from "discourse/lib/lightbox";

//...

setupLightboxes({
   container: document.querySelector(".my-container"),
   selector: ".my-selector"
})

Pour que le bouton ouvre la lightbox, il suffit d’ajouter data-lightbox-trigger comme ceci :

<button data-lightbox-trigger>Ouvrir la lightbox</button>

Le reste est géré automatiquement.

Enfin, chaque fois que vous voulez nettoyer, appelez :

cleanupLightboxes()

Le nettoyage n’est pas vraiment critique car le service lightbox nettoiera automatiquement à chaque fois que l’événement dom:clean se déclenche dans l’application (lors des transitions de route).

Écouter les événements de lightbox

La nouvelle lightbox déclenchera des événements, comme nous en avons discuté plus tôt. Ces événements sont :

  • lightbox:opened
  • lightbox:item-will-change
  • lightbox:item-did-change
  • lightbox:closed

lightbox:opened

Cet événement se déclenche lorsque la lightbox est ouverte et contient deux objets :

  1. items : c’est un tableau de toutes les images dans la lightbox actuelle. Chacune d’elles sera un objet.
  2. currentItem : c’est l’objet de l’élément actuel sur lequel la lightbox s’est ouverte.

Un objet élément ressemble à ceci :

{
  "fullsizeURL": "https://d11a6trkgmumsb.cloudfront.net/original/4X/2/3/c/23c5746c48803deac5c105081dba20555187c3ff.jpeg",
  "smallURL": "https://d11a6trkgmumsb.cloudfront.net/optimized/4X/2/3/c/23c5746c48803deac5c105081dba20555187c3ff_2_600x750.jpeg",
  "downloadURL": "/uploads/short-url/56rKTvkvmL6c2C8OFQtMo3D8sIn.jpeg?dl=1",
  "title": "Photo en gros plan d'un microphone noir sur pied",
  "fileDetails": "1200×1500 88,9 Ko",
  "dominantColor": "793C6D",
  "aspectRatio": "400 / 500",
  "index": 0,
  "cssVars": "--dominant-color: #793C6D;--aspect-ratio: 400 / 500;--small-url: url(https://d11a6trkgmumsb.cloudfront.net/optimized/4X/2/3/c/23c5746c48803deac5c105081dba20555187c3ff_2_600x750.jpeg);",
  "isLoaded": true,
  "hasLoadingError": false,
  "width": 1200,
  "height": 1500,
  "canZoom": true
}

lightbox:item-will-change

Cet événement se déclenche juste avant que l’élément actuel dans la lightbox ne change. Il contiendra currentItem (celui qui est sur le point de changer).

lightbox:item-did-change

Cet événement se déclenche juste après que l’élément dans la lightbox a changé et a fini de charger, et il aura currentItem comme argument.

lightbox:closed

Cet événement se déclenche juste après que la lightbox est fermée et n’a aucun argument.

Avec les événements ci-dessus, un composant de thème théorique peut facilement ajouter de l’analytique à la lightbox comme ceci :

api.onAppEvent('lightbox:opened', ({items, currentItem}) => {
  console.log({items});
  console.log({currentItem});

  // votre code d'analytique ici
});

ou d’autres idées similaires.

Le CSS

La nouvelle lightbox utilise la convention de nommage BEM pour les classes HTML. Voici une liste complète des sélecteurs que vous pouvez utiliser :

html.has-lightbox {
  // CSS pour l'élément HTML lorsque les lightboxes sont ouvertes
}

.d-lightbox {
  &--is-visible {
    // Élément principal de la lightbox
  }

  &__content {
    // Conteneur du contenu intérieur de la lightbox
  }
}

.d-lightbox {
  &__content__header {
    // En-tête de la lightbox
  }
}

.d-lightbox {
  &__content__body {
    // Corps de la lightbox (contient l'image principale)

    &__backdrop {
      // Arrière-plan (backdrop) de la lightbox
    }

    &__main-image {
      // Image principale de la lightbox
    }

    &__error-message {
      // Message d'erreur de la lightbox
    }

    &__previous-button,
    &__next-button {
      // Boutons précédent/suivant principaux de la lightbox
    }
  }
}

.d-lightbox {
  &__content__footer {
    // Pied de page de la lightbox

    &__main-title {
      // Titre de l'image de la lightbox
     
      &__item-file-details {
        // Détails du fichier de la lightbox, par ex. "1000x582 183Ko"
      }
    }
  }
}

.d-lightbox {
  &__content__carousel {
    // Conteneur du carrousel de la lightbox

    &__previous-button,
    &__next-button {
      // Boutons précédent/suivant du carrousel de la lightbox
    }
  }
}

.d-lightbox {
  &__content__carousel {
    &__carousel-items {
      // Conteneur des éléments du carrousel de la lightbox

      &__item,
      &__item--is-current {
        // Élément du carrousel de la lightbox
      }

      &__item--is-current {
        // Élément actuel du carrousel de la lightbox
      }
    }
  }
}

.d-lightbox {
  &--is-vertical &__content__carousel {
    // Styles verticaux du carrousel de la lightbox
  }
}

.d-lightbox {
  &--is-horizontal &__content__carousel {
    // Styles horizontaux du carrousel de la lightbox
  }
}

.d-lightbox {
  .btn-flat {
    // Styles pour tous les boutons de la lightbox
  }
}

.d-lightbox {
  &__content {
    &__focus-trap,
    &__screen-reader-announcer {
      // Piège de focus et annonceur de lecteur d'écran de la lightbox. Ceux-ci sont hors écran
    }
  }
}

/* Styles d'état */

// Carrousel
.d-lightbox {
  &--has-carousel {
    // Styles de la lightbox lorsque le carrousel est ouvert
  }
}

// Titre étendu
.d-lightbox {
  &--has-expanded-title {
    // Styles de la lightbox lorsque le titre est étendu
  }
}

// Zoom
.d-lightbox {
  &--can-zoom {
    // Styles de la lightbox lorsque l'image peut être zoomée
  }

  &--is-zoomed {
    // Styles de la lightbox lorsque l'image est zoomée
  }
}

// Rotation
.d-lightbox {
  &--is-rotated {
    // Styles de la lightbox lorsque l'image est tournée
  }
}

// Plein écran
.d-lightbox {
  &--is-fullscreen {
    // Styles de la lightbox lorsque l'image est en plein écran
  }
}

Maintenant que nous avons couvert le quoi, nous pouvons enfin passer à…

Le quand

Pour l’instant, la PR est prête pour examen, ce qui doit d’abord avoir lieu. Après qu’elle aura passé l’examen, elle sera disponible pour les sites qui mettent à jour. La PR ajoute un nouveau paramètre de site temporaire pendant la transition de Magnific Popup vers Discourse Lightbox. Le nom du paramètre est :

enable_experimental_lightbox

Si le paramètre est désactivé, la PR n’aura aucun effet et tout continuera de fonctionner comme avant avec Magnific Popup.

Discourse Lightbox remplacera Magnific Popup dans les messages cuits, les messages de chat et les composants de téléverseur d’images lorsque le paramètre sera activé.

Feuille de route

  1. Examen de la PR
  2. Fusion de la PR
  3. Période de feedback général (1-2 semaines)
  4. PR pour supprimer Magnific Popup du noyau et supprimer le paramètre de site expérimental.
  5. À déterminer : objectifs d’étairement tels qu’un composant de thème explorant différentes mises en page (devrait être simple car la nouvelle lightbox utilise CSS Grid pour la mise en page).

Remerciements

  • Ce travail a été généreusement sponsorisé par CDCK :pray:
  • Beaucoup d’amour :heart: va à Dmytro Semenov, le créateur de Magnific Popup, pour avoir créé quelque chose qui était bien en avance sur son temps.
  • Les images utilisées dans les démos ci-dessus sont gracieuseté de Irina Iriser @pexels.
38 « J'aime »

J’ai l’habitude, sur YouTube et d’autres applications de bureau, que la touche F passe en mode plein écran.
Y a-t-il une raison de ne pas utiliser la mémoire musculaire pour ce raccourci ?

4 « J'aime »

Celui-ci est particulièrement beau. :raised_hands:

Une chose que j’aurais souhaité, c’est de pouvoir passer aux images du message suivant tout en utilisant les flèches. De cette façon, si je suis dans un sujet comme « Chats mignons », je peux simplement utiliser les flèches pour naviguer de manière transparente vers les images du message suivant. Il y aurait diverses choses à prendre en considération, mais ce serait très bien. Actuellement, je suis obligé de fermer la lightbox, d’aller au message suivant, de cliquer sur la première image, …

16 « J'aime »

Bootstrap 3 nécessite également jQuery. Discourse utilise Bootstrap 3. Donc, jQuery sera installé comme une dépendance sur notre forum. Est-ce vrai ?

2 « J'aime »

EmberJS utilisait également jQuery et Discourse est une application EmberJS. Nous travaillons, depuis quelques années maintenant, à supprimer l’utilisation de jQuery de Discourse lui-même, des plugins officiels et des composants.

C’est beaucoup de travail, mais nous nous rapprochons. Ce sujet même est l’un des nombreux efforts en ce sens.

11 « J'aime »

Ceci a maintenant été implémenté. :partying_face:

Nous recueillerons des commentaires dans ce sujet pendant une courte période, alors jetez-y un coup d’œil et dites-nous ce que vous en pensez. :slight_smile: :+1:

6 « J'aime »