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 la fenêtre pour donner à votre PWA une expérience d'application.

Si vous vous souvenez de mon article Donner l'impression que votre PWA ressemble à une application, vous vous souvenez peut-être que j'ai mentionné la personnalisation de la barre de titre de votre application afin de créer une expérience semblable à celle d'une application. Voici un exemple d'affichage de l'application Podcasts sur macOS.

Barre de titre de l'application macOS Podcasts affichant les boutons des commandes multimédias et les métadonnées concernant le podcast en cours de lecture
Une barre de titre personnalisée donne à votre PWA une application spécifique à la plate-forme.

Vous serez peut-être tenté de vous opposer en déclarant 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 à lire les règles du navigateur. Vrai, mais la bonne nouvelle est que la fonctionnalité de superposition des commandes de fenêtre, dont il est question dans 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. Valeur "window-controls-overlay" pour le 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. Standardisation de la propriété CSS précédemment propriétaire -webkit-app-region en tant que propriété app-region pour définir des régions déplaçables dans le contenu Web.
  4. Un mécanisme permettant d'interroger et de contourner la région des contrôles 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, agrandir, fermer, etc.) et contient souvent le titre de l'application. La superposition des commandes de fenêtre permet aux progressive web apps (PWA) de créer une apparence d'application en remplaçant la barre de titre pleine largeur existante par une petite superposition contenant les commandes de la fenêtre. Cela permet aux développeurs de placer du contenu personnalisé dans ce qui était auparavant la zone de la barre de titre contrôlée par le navigateur.

État actuel

Step État
1. Créer une vidéo explicative Fin
2. Créer un brouillon initial de la spécification Fin
3. Recueillir des commentaires et itérer sur la conception En cours
4. Phase d'évaluation Terminé
5. Lancement Terminée (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" comme membre "display_override" principal dans le fichier manifeste de l'application Web:

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

La superposition des commandes de fenêtre n'est visible que si toutes les conditions suivantes sont remplies:

  1. L'application n'est pas ouverte dans le navigateur, mais dans une fenêtre distincte de la PWA.
  2. Le fichier manifeste inclut "display_override": ["window-controls-overlay"]. (Les autres valeurs sont ensuite autorisées.)
  3. La PWA s'exécute sur le système d'exploitation d'un ordinateur de bureau.
  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 standards à gauche ou à droite, en fonction du système d'exploitation.

Fenêtre d'application avec une barre de titre vide et les commandes des fenêtres à gauche
Barre de titre vide prête pour le contenu personnalisé.

Déplacer du contenu dans la barre de titre

Maintenant que la barre de titre contient de l'espace, vous pouvez déplacer un élément à cet endroit. Pour cet article, j'ai créé une PWA de contenus spéciaux Wikimedia. Une fonctionnalité utile pour cette application peut être la recherche de mots dans les titres d'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 vers le haut dans la barre de titre, vous avez besoin du 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 en fait le cas.

Une fenêtre d&#39;application avec une barre de recherche dans la barre de titre.
La nouvelle barre de titre est active et responsive.

Déterminer quelles parties de la barre de titre peuvent être déplaçables

Bien que la capture d'écran ci-dessus suggère que vous avez terminé, vous n'avez pas encore terminé. La fenêtre de la PWA ne peut plus être déplaçable (à part une très petite zone), car les boutons des commandes de fenêtre ne sont pas des zones de déplacement, et le reste de la barre de titre comprend le widget de recherche. Corrigez ce problème à l'aide de la propriété CSS app-region avec la valeur drag. Dans le cas concret, il est possible de faire glisser tout autre élément que l'élément input.

/* 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;
}

Une fois 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. La requête de recherche peut donc être saisie.

Détection de fonctionnalités

La compatibilité avec la superposition des commandes de fenêtre peut être détectée en testant l'existence de windowControlsOverlay:

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

Interroger la région de contrôle de la fenêtre avec windowControlsOverlay

Jusqu'à présent, le code présente un problème: sur certaines plates-formes, les commandes de fenêtre se trouvent à droite, et sur d'autres à gauche. Pour ne rien arranger, le menu Chrome à trois points change également de position, en fonction de la plate-forme. Cela signifie que l'image de fond en dégradé linéaire doit être adaptée de manière dynamique pour s'exécuter de #131313maroon ou maroon#131313maroon, de sorte qu'elle se fonde avec 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, vous pouvez interroger 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');
}

Plutôt que d'avoir directement l'image de fond dans les règles CSS de la classe .search (comme précédemment), le code modifié utilise désormais deux classes définies de manière dynamique par le code ci-dessus.

/* 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 superposition des commandes de fenêtre est visible

La superposition des commandes de fenêtre n'est en aucun cas visible dans la zone de la barre de titre. Bien qu'elle ne soit pas visible dans les navigateurs qui ne sont pas compatibles avec la fonctionnalité de superposition des commandes de fenêtre, elle ne l'est 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 en cas de 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 l'image de fond appropriée en fonction de l'emplacement des commandes de fenêtre. Dans d'autres cas, un contrôle plus précis est nécessaire. Par exemple, vous pouvez adapter la superposition des commandes de fenêtre en fonction de l'espace disponible et ajouter une blague directement dans la superposition des commandes de fenêtre lorsque l'espace est suffisant.

Fenêtre de contrôle de la zone de superposition sur une fenêtre étroite avec du texte raccourci.
Commandes de la barre de titre adaptées à une fenêtre étroite.

Vous pouvez être averti des changements 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 défini sur 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. Consultez la page MDN pour en savoir plus sur les différences entre les deux.

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

Compatibilité avec les applications exécutées dans un onglet et sur des navigateurs non compatibles

Deux cas sont possibles:

  • Cas où une application s'exécute dans un navigateur compatible avec la superposition des commandes de fenêtre, mais lorsqu'elle est utilisée dans un onglet de navigateur.
  • Cas où une application s'exécute dans un navigateur non compatible avec la superposition des commandes de fenêtre.

Dans les deux cas, par défaut, le code HTML créé pour la superposition des commandes de fenêtre s'affiche de manière intégrée comme du contenu HTML standard, et les valeurs de remplacement des variables env() sont appliquées au positionnement. Dans les navigateurs compatibles, vous pouvez également décider de ne pas afficher le code HTML désigné pour la superposition des commandes de fenêtre en vérifiant la propriété visible de la superposition. Si elle indique false, vous pouvez masquer ce contenu HTML.

PWA exécutée dans un onglet de navigateur, avec la superposition des commandes de fenêtre affichée dans le corps
Sur les anciens navigateurs, les commandes destinées à la barre de titre peuvent être facilement affichées dans le corps de texte.

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

PWA exécutée en mode autonome avec la superposition des commandes de fenêtre affichée dans le corps.
Sur les anciens navigateurs, les commandes destinées à la barre de titre peuvent être facilement affichées dans le corps de texte.

Remarques sur l'interface utilisateur

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

Si votre application s'affiche en plein écran, réfléchissez bien à la nécessité d'intégrer la superposition des commandes de fenêtre à la vue plein écran. Vous pouvez éventuellement réorganiser votre mise en page lorsque l'événement onfullscreenchange se déclenche.

Démonstration

J'ai créé une démonstration que vous pouvez utiliser dans différents navigateurs compatibles ou non, à l'état installé ou non. Pour l'expérience réelle de la superposition des commandes de fenêtre, vous devez installer l'application. Vous pouvez voir deux captures d'écran ci-dessous. Le code source de l'application est disponible sur Glitch.

Application de démonstration Wikimedia de contenu sélectionné avec la superposition des commandes de fenêtre
L'application de démonstration est disponible pour des tests.

La fonctionnalité de recherche dans la superposition des commandes de fenêtre est entièrement fonctionnelle:

Application de démonstration de contenu sélectionné de Wikimedia avec la superposition des commandes de fenêtre et la recherche active du terme &quot;cléopa...&quot; mettant en évidence l&#39;un des articles contenant le terme &quot;Cléopâtre&quot;
Fonctionnalité de recherche utilisant la superposition des commandes de fenêtre.

Points à noter concernant la sécurité

L'équipe Chromium a conçu et mis en œuvre l'API Window Controls Overlay en suivant les principes fondamentaux définis dans la section Contrôler l'accès aux fonctionnalités puissantes de la plate-forme Web, comme le contrôle utilisateur, la transparence et l'ergonomie.

Spoofing

Donner aux sites un contrôle partiel de la barre de titre permet aux développeurs de falsifier du contenu dans une région qui était auparavant une région fiable et contrôlée par le navigateur. Actuellement, dans les navigateurs Chromium, le mode autonome comprend une barre de titre qui, lors du 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). Après quelques secondes, le texte d'origine disparaît. Si le navigateur est défini sur une langue se lisant de droite à gauche, cette mise en page est inversée de sorte que le texte d'origine se trouve sur la gauche. La superposition des commandes de la fenêtre s'ouvre pour simuler l'origine si la marge intérieure est insuffisante entre l'origine et le bord droit de la superposition. Par exemple, l'origine "evil.ltd" peut être ajoutée à l'origine du site de confiance "google.com", laissant croire aux utilisateurs que la source est digne de confiance. L'objectif est de conserver ce texte afin que les utilisateurs sachent quelle est l'origine de l'application et qu'il répond à leurs attentes. Pour les navigateurs configurés de droite à gauche, il doit y avoir une marge intérieure suffisante à droite du texte de l'origine pour empêcher un site Web malveillant d'ajouter une origine non sécurisée à une origine fiable.

Empreinte digitale

L'activation de la superposition des commandes de fenêtre et des régions déplaçables ne pose pas de problèmes de confidentialité importants, hormis la détection des fonctionnalités. Toutefois, en raison des différences de taille et de position des boutons de commande de fenêtre selon les systèmes d'exploitation, la méthode navigator.windowControlsOverlay.getTitlebarAreaRect() renvoie un DOMRect dont la position et les dimensions indiquent 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 user-agent, mais en raison de problèmes liés au fingerprinting, il existe une discussion autour du gel de la chaîne UA et de l'unification des versions d'OS. La communauté des navigateurs s'efforce constamment de comprendre à quelle fréquence la taille de la superposition des commandes de fenêtre change entre les plates-formes, car l'hypothèse actuelle est qu'elles sont relativement stables entre les versions d'OS et ne seraient donc pas utiles pour observer les versions mineures du système d'exploitation. Bien qu'il s'agisse d'un problème potentiel d'empreinte digitale, il ne s'applique qu'aux PWA installées qui utilisent la fonctionnalité de barre de titre personnalisée et ne s'applique pas à l'utilisation générale du navigateur. De plus, l'API navigator.windowControlsOverlay ne sera pas disponible pour les iFrames intégrés à une PWA.

Si vous accédez à une autre origine dans une PWA, celle-ci revient à la barre de titre autonome normale, même si elle répond aux critères ci-dessus et qu'elle 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 origine différente. Après le retour à l'origine d'origine, la superposition des commandes de fenêtre est à nouveau utilisée.

Barre d&#39;URL noire pour la navigation en dehors de l&#39;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.

Décrivez-nous la conception de l'API.

Y a-t-il quelque chose dans l'API qui ne fonctionne pas comme prévu ? Ou 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 de spécification dans le dépôt GitHub correspondant ou ajoutez vos commentaires à un problème existant.

Signaler un problème d'implémentation

Avez-vous détecté un bug dans l'implémentation de Chromium ? Ou l'implémentation est-elle différente des spécifications ? Signalez un bug à l'adresse new.crbug.com. Veillez à inclure autant de détails que possible, ainsi que des instructions simples pour reproduire le bug, puis saisissez UI>Browser>WebAppInstalls dans la zone Composants. Glitch est idéal pour partager des reproductions simples et rapides.

Afficher la compatibilité avec l'API

Comptez-vous utiliser l'API Window Controls Overlay ? Votre assistance publique 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 contenant le hashtag #WindowControlsOverlay, et indiquez-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é lu par Joe Medley et Kenneth Rohde Christiansen. Image héros par Sigmund sur Unsplash.