Personnaliser les commandes de fenêtre en superposition de la barre de titre de votre PWA

Utilisez la zone de la barre de titre à côté des commandes de fenêtre pour que votre PWA ressemble davantage à une application.

Si vous vous souvenez de mon article Make your PWA feel more like an app, vous vous rappellerez peut-être que j'ai mentionné la personnalisation de la barre de titre de votre application comme stratégie pour créer une expérience plus semblable à celle d'une application. Voici un exemple de ce à quoi cela peut ressembler dans l'application Podcasts de macOS.

Barre de titre de l'application Podcasts de macOS affichant les boutons de commande multimédia et les métadonnées du podcast en cours de lecture.
Une barre de titre personnalisée donne à votre PWA l'impression d'être une application spécifique à une plate-forme.

Vous pourriez être tenté de vous y opposer en disant que Podcasts est une application macOS spécifique à la plate-forme qui ne s'exécute pas dans un navigateur et peut donc faire ce qu'elle veut sans avoir à respecter les règles du navigateur. C'est vrai, mais la bonne nouvelle, c'est que la fonctionnalité de superposition des contrôles de fenêtre, qui est le sujet de cet article, vous permettra bientôt de créer des interfaces utilisateur similaires pour votre PWA.

Composants de la superposition des commandes de fenêtre

La superposition des commandes de fenêtre se compose de quatre sous-fonctionnalités :

  1. La valeur "window-controls-overlay" du champ "display_override" dans le fichier manifeste de l'application Web.
  2. Les variables d'environnement CSS titlebar-area-x, titlebar-area-y, titlebar-area-width et titlebar-area-height.
  3. La propriété CSS propriétaire -webkit-app-region a été standardisée en tant que propriété app-region pour définir les régions déplaçables dans le contenu Web.
  4. Mécanisme permettant d'interroger et de contourner la région des commandes de fenêtre via le membre windowControlsOverlay de window.navigator.

Qu'est-ce que la superposition des commandes de fenêtre ?

La zone de la barre de titre fait référence à l'espace situé à gauche ou à droite des commandes de la fenêtre (c'est-à-dire les boutons permettant de réduire, d'agrandir, de fermer, etc.) et contient souvent le titre de l'application. La superposition des commandes de fenêtre permet aux applications Web progressives (PWA) de donner une impression plus proche des applications en remplaçant la barre de titre pleine largeur existante par une petite superposition contenant les commandes de fenêtre. Cela permet aux développeurs de placer du contenu personnalisé dans la zone de la barre de titre, qui était auparavant contrôlée par le navigateur.

État actuel

Étape État
1. Créer une explication Fin
2. Créer une première ébauche de spécification Fin
3. Recueillir des commentaires et améliorer la conception En cours
4. Essai Origin Trial Terminé
5. Lancement Terminé (dans Chromium 104)

Utiliser la superposition des commandes de fenêtre

Ajouter window-controls-overlay au fichier manifeste de l'application Web

Une progressive web app peut activer la superposition des commandes de fenêtre en ajoutant "window-controls-overlay" en tant que membre "display_override" principal dans le fichier manifeste de l'application Web :

{
  "display_override": ["window-controls-overlay"]
}

La superposition des commandes de fenêtre ne sera visible que si toutes les conditions suivantes sont remplies :

  1. L'application ne s'ouvre pas dans le navigateur, mais dans une fenêtre PWA distincte.
  2. Le fichier manifeste inclut "display_override": ["window-controls-overlay"]. (D'autres valeurs sont autorisées par la suite.)
  3. La PWA s'exécute sur un système d'exploitation pour ordinateur.
  4. L'origine actuelle correspond à celle pour laquelle la PWA a été installée.

Il en résulte une zone de barre de titre vide avec les commandes de fenêtre habituelles à gauche ou à droite, selon le système d'exploitation.

Fenêtre d'application avec une barre de titre vide et les commandes de fenêtre sur la gauche.
Barre de titre vide, prête à recevoir du contenu personnalisé.

Déplacer du contenu dans la barre de titre

Maintenant qu'il y a de l'espace dans la barre de titre, vous pouvez y déplacer un élément. Pour cet article, j'ai créé une PWA de contenu sélectionné de Wikimedia. Une fonctionnalité utile pour cette application peut être une recherche de mots dans les titres des articles. Le code HTML de la fonctionnalité de recherche se présente comme suit :

<div class="search">
  <img src="logo.svg" alt="Wikimedia logo." width="32" height="32" />
  <label>
    <input type="search" />
    Search for words in articles
  </label>
</div>

Pour déplacer ce div dans la barre de titre, vous avez besoin de CSS :

.search {
  /* Make sure the `div` stays there, even when scrolling. */
  position: fixed;
  /**
   * Gradient, because why not. Endless opportunities.
   * The gradient ends in `#36c`, which happens to be the app's
   * `<meta name="theme-color" content="#36c">`.
   */
  background-image: linear-gradient(90deg, #36c, #131313, 33%, #36c);
  /* Use the environment variable for the left anchoring with a fallback. */
  left: env(titlebar-area-x, 0);
  /* Use the environment variable for the top anchoring with a fallback. */
  top: env(titlebar-area-y, 0);
  /* Use the environment variable for setting the width with a fallback. */
  width: env(titlebar-area-width, 100%);
  /* Use the environment variable for setting the height with a fallback. */
  height: env(titlebar-area-height, 33px);
}

Vous pouvez voir l'effet de ce code dans la capture d'écran ci-dessous. La barre de titre est entièrement responsive. Lorsque vous redimensionnez la fenêtre de la PWA, la barre de titre réagit comme si elle était composée de contenu HTML standard, ce qui est le cas.

Fenêtre d&#39;application avec une barre de recherche dans la barre de titre.
La nouvelle barre de titre est active et réactive.

Déterminer quelles parties de la barre de titre sont déplaçables

Bien que la capture d'écran ci-dessus suggère que vous avez terminé, ce n'est pas encore le cas. La fenêtre de la PWA n'est plus déplaçable (sauf dans une très petite zone), car les boutons de commande de la fenêtre ne sont pas des zones de déplacement, et le reste de la barre de titre est constitué du widget de recherche. Pour résoudre ce problème, utilisez la propriété CSS app-region avec la valeur drag. Dans le cas concret, il est acceptable de rendre tout ce qui n'est pas l'élément input déplaçable.

/* The entire search `div` is draggable… */
.search {
  -webkit-app-region: drag;
  app-region: drag;
}

/* …except for the `input`. */
input {
  -webkit-app-region: no-drag;
  app-region: no-drag;
}

Avec ce CSS en place, l'utilisateur peut faire glisser la fenêtre de l'application comme d'habitude en faisant glisser div, img ou label. Seul l'élément input est interactif, ce qui permet de saisir la requête de recherche.

Détection de caractéristiques

La compatibilité avec la barre de titre peut être détectée en testant l'existence de windowControlsOverlay :

if ('windowControlsOverlay' in navigator) {
  // Window Controls Overlay is supported.
}

Interroger la région des commandes de fenêtre avec windowControlsOverlay

Le code présente un problème : sur certaines plates-formes, les commandes de fenêtre se trouvent à droite, tandis que sur d'autres, elles se trouvent à gauche. Pour ne rien arranger, le menu Chrome à trois points changera également de position en fonction de la plate-forme. Cela signifie que l'image d'arrière-plan à dégradé linéaire doit être adaptée de manière dynamique pour s'exécuter de #131313 à maroon ou de maroon à #131313 à maroon, afin qu'elle se fonde dans la couleur d'arrière-plan maroon de la barre de titre, qui est déterminée par <meta name="theme-color" content="maroon">. Pour ce faire, interrogez l'API getTitlebarAreaRect() sur la propriété navigator.windowControlsOverlay.

if ('windowControlsOverlay' in navigator) {
  const { x } = navigator.windowControlsOverlay.getTitlebarAreaRect();
  // Window controls are on the right (like on Windows).
  // Chrome menu is left of the window controls.
  // [ windowControlsOverlay___________________ […] [_] [■] [X] ]
  if (x === 0) {
    div.classList.add('search-controls-right');
  }
  // Window controls are on the left (like on macOS).
  // Chrome menu is right of the window controls overlay.
  // [ [X] [_] [■] ___________________windowControlsOverlay [⋮] ]
  else {
    div.classList.add('search-controls-left');
  }
} else {
  // When running in a non-supporting browser tab.
  div.classList.add('search-controls-right');
}

Au lieu d'avoir l'image d'arrière-plan directement dans les règles CSS de la classe .search (comme précédemment), le code modifié utilise désormais deux classes que le code ci-dessus définit de manière dynamique.

/* For macOS: */
.search-controls-left {
  background-image: linear-gradient(90deg, #36c, 45%, #131313, 90%, #36c);
}

/* For Windows: */
.search-controls-right {
  background-image: linear-gradient(90deg, #36c, #131313, 33%, #36c);
}

Déterminer si la barre de titre est visible

La superposition des commandes de fenêtre ne sera pas visible dans la zone de la barre de titre dans toutes les circonstances. Bien qu'il ne soit naturellement pas présent sur les navigateurs qui ne prennent pas en charge la fonctionnalité de superposition des contrôles de fenêtre, il ne le sera pas non plus lorsque la PWA en question s'exécute dans un onglet. Pour détecter cette situation, vous pouvez interroger la propriété visible de windowControlsOverlay :

if (navigator.windowControlsOverlay.visible) {
  // The window controls overlay is visible in the title bar area.
}

Vous pouvez également utiliser la requête média display-mode en JavaScript et/ou en CSS :

// Create the query list.
const mediaQueryList = window.matchMedia('(display-mode: window-controls-overlay)');

// Define a callback function for the event listener.
function handleDisplayModeChange(mql) {
  // React on display mode changes.
}

// Run the display mode change handler once.
handleDisplayChange(mediaQueryList);

// Add the callback function as a listener to the query list.
mediaQueryList.addEventListener('change', handleDisplayModeChange);
@media (display-mode: window-controls-overlay) { 
  /* React on display mode changes. */ 
}

Recevoir des notifications concernant les modifications de géométrie

Interroger la zone de superposition des commandes de fenêtre avec getTitlebarAreaRect() peut suffire pour des opérations ponctuelles, comme définir la bonne image d'arrière-plan en fonction de l'emplacement des commandes de fenêtre. Toutefois, dans d'autres cas, un contrôle plus précis est nécessaire. Par exemple, un cas d'utilisation possible pourrait être d'adapter la barre de titre en fonction de l'espace disponible et d'ajouter une blague directement dans la barre de titre lorsqu'il y a suffisamment d'espace.

Zone de superposition des commandes de fenêtre dans une fenêtre étroite avec du texte abrégé.
Commandes de la barre de titre adaptées à une fenêtre étroite.

Vous pouvez être averti des modifications de géométrie en vous abonnant à navigator.windowControlsOverlay.ongeometrychange ou en configurant un écouteur d'événements pour l'événement geometrychange. Cet événement ne se déclenche que lorsque la superposition des commandes de fenêtre est visible, c'est-à-dire lorsque navigator.windowControlsOverlay.visible est true.

const debounce = (func, wait) => {
  let timeout;
  return function executedFunction(...args) {
    const later = () => {
      clearTimeout(timeout);
      func(...args);
    };
    clearTimeout(timeout);
    timeout = setTimeout(later, wait);
  };
};

if ('windowControlsOverlay' in navigator) {
  navigator.windowControlsOverlay.ongeometrychange = debounce((e) => {
    span.hidden = e.titlebarAreaRect.width < 800;
  }, 250);
}

Plutôt que d'attribuer une fonction à ongeometrychange, vous pouvez également ajouter un écouteur d'événements à windowControlsOverlay comme ci-dessous. Pour en savoir plus sur la différence entre les deux, consultez MDN.

navigator.windowControlsOverlay.addEventListener(
  'geometrychange',
  debounce((e) => {
    span.hidden = e.titlebarAreaRect.width < 800;
  }, 250),
);

Compatibilité lors de l'exécution dans un onglet et sur des navigateurs non compatibles

Deux cas de figure sont possibles :

  • Cas où une application s'exécute dans un navigateur compatible avec Window Controls Overlay, mais où l'application est utilisée dans un onglet de navigateur.
  • Le cas où une application s'exécute dans un navigateur qui n'est pas compatible avec la barre de titre.

Dans les deux cas, par défaut, le code HTML créé pour l'overlay des commandes de fenêtre s'affichera en ligne comme du contenu HTML normal, et les valeurs de remplacement des variables env() seront utilisées pour le positionnement. Dans les navigateurs compatibles, vous pouvez également choisir de ne pas afficher le code HTML désigné pour la superposition des commandes de fenêtre en cochant la propriété visible de la superposition. Si elle renvoie false, masquez ce contenu HTML.

Une PWA s&#39;exécutant dans un onglet de navigateur avec la superposition des commandes de fenêtre affichée dans le corps.
Les commandes destinées à la barre de titre peuvent facilement être affichées dans le corps sur les anciens navigateurs.

Pour rappel, les navigateurs non compatibles ne tiendront pas compte de la propriété "display_override" du fichier manifeste de l'application Web ou ne reconnaîtront pas "window-controls-overlay" et utiliseront donc la prochaine valeur possible selon la chaîne de secours, par exemple "standalone".

Une PWA s&#39;exécutant en mode autonome avec la superposition des commandes de fenêtre affichée dans le corps.
Les commandes destinées à la barre de titre peuvent facilement être affichées dans le corps sur les anciens navigateurs.

Considérations relatives à l'UI

Bien que cela puisse être tentant, il n'est pas recommandé de créer un menu déroulant classique dans la zone de superposition des contrôles de fenêtre. Cela enfreindrait les consignes de conception sur macOS, une plate-forme sur laquelle les utilisateurs s'attendent à trouver des barres de menu (fournies par le système ou personnalisées) en haut de l'écran.

Si votre application offre une expérience en plein écran, réfléchissez bien à l'opportunité d'intégrer la superposition des contrôles de fenêtre à la vue en plein écran. Vous pouvez réorganiser votre mise en page lorsque l'événement onfullscreenchange se déclenche.

Démo

J'ai créé une démonstration que vous pouvez tester dans différents navigateurs compatibles et non compatibles, ainsi qu'avec l'application installée ou non. Pour profiter de l'expérience réelle de la superposition des contrôles de fenêtre, vous devez installer l'application. Vous trouverez ci-dessous deux captures d'écran de ce à quoi vous pouvez vous attendre. Le code source de l'application est disponible sur Glitch.

Application de démonstration Wikimedia Featured Content avec superposition des commandes de fenêtre.
L'application de démonstration est disponible pour les tests.

La fonctionnalité de recherche dans la barre de titre est entièrement fonctionnelle :

Application de démonstration Wikimedia Featured Content avec superposition des contrôles de fenêtre et recherche active du terme &quot;cleopa…&quot; mettant en évidence l&#39;un des articles avec le terme correspondant &quot;Cléopâtre&quot;.
Fonctionnalité de recherche utilisant la superposition des commandes de fenêtre.

Considérations de sécurité

L'équipe Chromium a conçu et implémenté l'API Window Controls Overlay en utilisant les principes de base définis dans Controlling Access to Powerful Web Platform Features, y compris le contrôle utilisateur, la transparence et l'ergonomie.

Spoofing

En donnant aux sites un contrôle partiel de la barre de titre, les développeurs peuvent usurper du contenu dans une zone qui était auparavant contrôlée par le navigateur et considérée comme fiable. Actuellement, dans les navigateurs Chromium, le mode autonome inclut une barre de titre qui, au lancement initial, affiche le titre de la page Web à gauche et l'origine de la page à droite (suivie du bouton "Paramètres et plus" et des commandes de la fenêtre). Au bout de quelques secondes, le texte d'origine disparaît. Si le navigateur est défini sur une langue qui se lit de droite à gauche, cette mise en page est inversée de sorte que le texte d'origine se trouve à gauche. Cela ouvre la superposition des commandes de fenêtre pour simuler l'origine s'il n'y a pas assez de marge intérieure entre l'origine et le bord droit de la superposition. Par exemple, l'origine "evil.ltd" peut être associée à un site de confiance "google.com", ce qui amène les utilisateurs à croire que la source est fiable. Nous prévoyons de conserver ce texte d'origine afin que les utilisateurs sachent d'où provient l'application et puissent s'assurer qu'elle correspond à leurs attentes. Pour les navigateurs configurés en RTL, il doit y avoir suffisamment de marge intérieure à droite du texte d'origine pour empêcher un site Web malveillant d'ajouter l'origine non sécurisée à une origine de confiance.

Empreinte numérique

L'activation de la barre de titre et des régions déplaçables ne pose pas de problème de confidentialité majeur, à l'exception de la détection des fonctionnalités. Toutefois, en raison des différences de taille et de position des boutons de contrôle de la fenêtre selon les systèmes d'exploitation, la méthode navigator.windowControlsOverlay.getTitlebarAreaRect() renvoie un DOMRect dont la position et les dimensions révèlent des informations sur le système d'exploitation sur lequel le navigateur s'exécute. Actuellement, les développeurs peuvent déjà découvrir l'OS à partir de la chaîne de l'agent utilisateur, mais en raison des problèmes d'empreinte digitale, il est question de figer la chaîne de l'agent utilisateur et d'unifier les versions de l'OS. La communauté des navigateurs s'efforce actuellement de comprendre la fréquence à laquelle la taille de la superposition des contrôles de fenêtre change sur les différentes plates-formes, car l'hypothèse actuelle est que ces contrôles sont assez stables sur les différentes versions d'OS et ne seraient donc pas utiles pour observer les versions mineures de l'OS. Bien qu'il s'agisse d'un problème potentiel d'empreinte numérique, il ne s'applique qu'aux PWA installées qui utilisent la fonctionnalité de barre de titre personnalisée et non à l'utilisation générale du navigateur. De plus, l'API navigator.windowControlsOverlay ne sera pas disponible pour les iFrames intégrés dans une PWA.

Si vous accédez à une autre origine dans une PWA, elle reviendra à la barre de titre autonome normale, même si elle répond aux critères ci-dessus et est lancée avec la superposition des commandes de fenêtre. Cela permet de tenir compte de la barre noire qui s'affiche lors de la navigation vers une autre origine. Une fois que vous êtes revenu à l'origine d'origine, la superposition des commandes de fenêtre sera à nouveau utilisée.

Barre d&#39;URL noire pour la navigation hors origine.
Une barre noire s'affiche lorsque l'utilisateur accède à une autre origine.

Commentaires

L'équipe Chromium souhaite connaître votre avis sur l'API Window Controls Overlay.

Parlez-nous de la conception de l'API

Y a-t-il quelque chose dans l'API qui ne fonctionne pas comme prévu ? Ou bien manque-t-il des méthodes ou des propriétés dont vous avez besoin pour mettre en œuvre votre idée ? Vous avez une question ou un commentaire sur le modèle de sécurité ? Signalez un problème lié aux spécifications dans le dépôt GitHub correspondant ou ajoutez vos commentaires à un problème existant.

Signaler un problème d'implémentation

Avez-vous trouvé un bug dans l'implémentation de Chromium ? Ou l'implémentation est-elle différente de la spécification ? Signalez un bug sur new.crbug.com. Veillez à inclure autant de détails que possible, des instructions simples pour reproduire le problème et saisissez UI>Browser>WebAppInstalls dans la zone Composants.

Soutenir l'API

Comptez-vous utiliser l'API Window Controls Overlay ? Votre soutien public aide l'équipe Chromium à hiérarchiser les fonctionnalités et montre aux autres fournisseurs de navigateurs à quel point il est essentiel de les prendre en charge.

Envoyez un tweet à @ChromiumDev avec le hashtag #WindowControlsOverlay et dites-nous où et comment vous l'utilisez.

Liens utiles

Remerciements

La superposition des commandes de fenêtre a été implémentée et spécifiée par Amanda Baker de l'équipe Microsoft Edge. Cet article a été examiné par Joe Medley et Kenneth Rohde Christiansen. Image héros de Sigmund sur Unsplash.