Menyesuaikan overlay kontrol jendela pada kolom judul PWA Anda

Gunakan area panel judul di samping kontrol jendela untuk membuat PWA Anda terasa lebih seperti aplikasi.

Jika Anda ingat artikel saya yang berjudul Membuat PWA Anda terasa lebih seperti aplikasi, Anda mungkin ingat bagaimana saya menyebutkan menyesuaikan kolom judul aplikasi Anda sebagai strategi untuk menciptakan pengalaman yang lebih seperti aplikasi. Berikut adalah contoh tampilannya yang menampilkan aplikasi Podcast macOS.

Kolom judul aplikasi Podcast macOS yang menampilkan tombol kontrol media dan metadata tentang podcast yang sedang diputar.
Panel judul kustom membuat PWA Anda terasa lebih seperti aplikasi khusus platform.

Sekarang Anda mungkin tergoda untuk menolak dengan mengatakan bahwa Podcast adalah aplikasi macOS khusus platform yang tidak berjalan di browser dan oleh karena itu dapat melakukan apa pun yang diinginkannya tanpa harus mematuhi aturan browser. Memang benar, tetapi kabar baiknya adalah fitur Overlay Kontrol Jendela, yang menjadi topik artikel ini, akan segera memungkinkan Anda membuat antarmuka pengguna serupa untuk PWA Anda.

Komponen Overlay Kontrol Jendela

Overlay Kontrol Jendela terdiri dari empat sub-fitur:

  1. Nilai "window-controls-overlay" untuk kolom "display_override" dalam manifes aplikasi web.
  2. Variabel lingkungan CSS titlebar-area-x, titlebar-area-y, titlebar-area-width, dan titlebar-area-height.
  3. Standardisasi properti CSS -webkit-app-region yang sebelumnya bersifat eksklusif sebagai properti app-region untuk menentukan wilayah yang dapat ditarik dalam konten web.
  4. Mekanisme untuk membuat kueri dan mengatasi masalah wilayah kontrol jendela melalui anggota windowControlsOverlay dari window.navigator.

Apa itu Overlay Kontrol Jendela

Area kolom judul mengacu pada ruang di sebelah kiri atau kanan kontrol jendela (yaitu, tombol untuk meminimalkan, memaksimalkan, menutup, dll.) dan sering kali berisi judul aplikasi. Overlay Kontrol Jendela memungkinkan progressive web application (PWA) memberikan nuansa yang lebih seperti aplikasi dengan menukar panel judul lebar penuh yang ada dengan overlay kecil yang berisi kontrol jendela. Hal ini memungkinkan developer menempatkan konten kustom di area kolom judul yang sebelumnya dikontrol browser.

Status saat ini

Langkah Status
1. Membuat penjelasan Selesai
2. Buat draf awal spesifikasi Selesai
3. Mengumpulkan masukan & mengulangi desain Sedang diproses
4. Uji coba origin Selesai
5. Peluncuran Selesai (di Chromium 104)

Cara menggunakan Overlay Kontrol Jendela

Menambahkan window-controls-overlay ke manifes aplikasi web

Aplikasi web progresif dapat mengaktifkan overlay kontrol jendela dengan menambahkan "window-controls-overlay" sebagai anggota "display_override" utama dalam manifes aplikasi web:

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

Overlay kontrol jendela hanya akan terlihat jika semua kondisi berikut terpenuhi:

  1. Aplikasi tidak dibuka di browser, tetapi di jendela PWA terpisah.
  2. Manifes mencakup "display_override": ["window-controls-overlay"]. (Nilai lain diizinkan setelahnya.)
  3. PWA berjalan di sistem operasi desktop.
  4. Origin saat ini cocok dengan origin tempat PWA diinstal.

Hasilnya adalah area kolom judul kosong dengan kontrol jendela reguler di kiri atau kanan, bergantung pada sistem operasi.

Jendela aplikasi dengan kolom judul kosong dengan kontrol jendela di sebelah kiri.
Kolom judul kosong yang siap untuk konten kustom.

Memindahkan konten ke kolom judul

Sekarang ada ruang di panel judul, Anda dapat memindahkan sesuatu ke sana. Untuk artikel ini, saya membuat PWA Konten Unggulan Wikimedia. Fitur yang berguna untuk aplikasi ini mungkin adalah penelusuran kata dalam judul artikel. HTML untuk fitur penelusuran akan terlihat seperti ini:

<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>

Untuk memindahkan div ini ke atas ke dalam kolom judul, beberapa CSS diperlukan:

.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);
}

Anda dapat melihat efek kode ini pada screenshot di bawah. Kolom judul sepenuhnya responsif. Saat Anda mengubah ukuran jendela PWA, panel judul akan bereaksi seolah-olah terdiri dari konten HTML biasa, yang memang demikian.

Jendela aplikasi dengan kotak penelusuran di kolom judul.
Panel judul baru aktif dan responsif.

Menentukan bagian mana dari kolom judul yang dapat ditarik

Meskipun screenshot di atas menunjukkan bahwa Anda sudah selesai, Anda belum selesai sepenuhnya. Jendela PWA tidak lagi dapat ditarik (kecuali area yang sangat kecil), karena tombol kontrol jendela bukan area penarikan, dan bagian panel judul lainnya terdiri dari widget penelusuran. Perbaiki hal ini menggunakan properti CSS app-region dengan nilai drag. Dalam kasus konkret, Anda dapat membuat semua elemen selain input dapat ditarik.

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

Dengan CSS ini, pengguna dapat menarik jendela aplikasi seperti biasa dengan menarik div, img, atau label. Hanya elemen input yang interaktif sehingga kueri penelusuran dapat dimasukkan.

Deteksi fitur

Dukungan untuk Overlay Kontrol Jendela dapat dideteksi dengan menguji keberadaan windowControlsOverlay:

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

Membuat kueri wilayah kontrol jendela dengan windowControlsOverlay

Sejauh ini, kode memiliki satu masalah: di beberapa platform, kontrol jendela berada di sebelah kanan, di platform lain, kontrol jendela berada di sebelah kiri. Lebih buruk lagi, menu Chrome "tiga titik" juga akan berubah posisi, berdasarkan platform. Artinya, gambar latar belakang gradien linear perlu disesuaikan secara dinamis agar berjalan dari #131313maroon atau maroon#131313maroon, sehingga menyatu dengan warna latar belakang maroon pada kolom judul yang ditentukan oleh <meta name="theme-color" content="maroon">. Hal ini dapat dilakukan dengan membuat kueri API getTitlebarAreaRect() pada properti 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');
}

Daripada memiliki gambar latar di aturan CSS class .search secara langsung (seperti sebelumnya), kode yang diubah kini menggunakan dua class yang ditetapkan kode di atas secara dinamis.

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

Menentukan apakah overlay kontrol jendela terlihat

Overlay kontrol jendela tidak akan terlihat di area kolom judul dalam semua situasi. Meskipun secara alami tidak ada di browser yang tidak mendukung fitur Overlay Kontrol Jendela, tombol ini juga tidak akan ada saat PWA yang dimaksud berjalan di tab. Untuk mendeteksi situasi ini, Anda dapat mengirim kueri properti visible dari windowControlsOverlay:

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

Atau, Anda juga dapat menggunakan kueri media display-mode di JavaScript dan/atau 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. */ 
}

Mendapatkan notifikasi tentang perubahan geometri

Mengueri area overlay kontrol jendela dengan getTitlebarAreaRect() sudah cukup untuk hal-hal sekali pakai seperti menyetel gambar latar belakang yang benar berdasarkan lokasi kontrol jendela, tetapi dalam kasus lain, kontrol yang lebih terperinci diperlukan. Misalnya, kasus penggunaan yang mungkin terjadi adalah mengadaptasi overlay kontrol jendela berdasarkan ruang yang tersedia dan menambahkan lelucon tepat di overlay kontrol jendela jika ada cukup ruang.

Area overlay kontrol jendela pada jendela sempit dengan teks yang disingkat.
Kontrol panel judul disesuaikan dengan jendela sempit.

Anda dapat diberi tahu tentang perubahan geometri dengan berlangganan navigator.windowControlsOverlay.ongeometrychange atau dengan menyiapkan pemroses peristiwa untuk peristiwa geometrychange. Peristiwa ini hanya akan diaktifkan saat overlay kontrol jendela terlihat, yaitu saat navigator.windowControlsOverlay.visible adalah 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);
}

Daripada menetapkan fungsi ke ongeometrychange, Anda juga dapat menambahkan pemroses peristiwa ke windowControlsOverlay seperti di bawah. Anda dapat membaca perbedaan antara keduanya di MDN.

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

Kompatibilitas saat berjalan di tab dan di browser yang tidak mendukung

Ada dua kemungkinan kasus yang perlu dipertimbangkan:

  • Kasus saat aplikasi berjalan di browser yang mendukung Window Controls Overlay, tetapi aplikasi digunakan di tab browser.
  • Kasus saat aplikasi berjalan di browser yang tidak mendukung Overlay Kontrol Jendela.

Dalam kedua kasus, secara default, HTML yang dibuat untuk overlay kontrol jendela akan ditampilkan inline seperti konten HTML biasa dan nilai penggantian variabel env() akan diterapkan untuk penentuan posisi. Di browser yang mendukung, Anda juga dapat memutuskan untuk tidak menampilkan HTML yang ditetapkan untuk overlay kontrol jendela dengan memeriksa properti visible overlay, dan jika properti tersebut melaporkan false, maka sembunyikan konten HTML tersebut.

PWA yang berjalan di tab browser dengan overlay kontrol jendela ditampilkan di bagian isi.
Kontrol yang ditujukan untuk kolom judul dapat ditampilkan dengan mudah di isi pada browser lama.

Sebagai pengingat, browser yang tidak mendukung tidak akan mempertimbangkan properti manifes aplikasi web "display_override" sama sekali, atau tidak mengenali "window-controls-overlay" sehingga menggunakan nilai berikutnya yang mungkin sesuai dengan rantai penggantian, misalnya, "standalone".

PWA yang berjalan dalam mode mandiri dengan overlay kontrol jendela yang ditampilkan di bagian isi.
Kontrol yang ditujukan untuk kolom judul dapat ditampilkan dengan mudah di isi pada browser lama.

Pertimbangan UI

Meskipun mungkin menarik, membuat menu dropdown klasik di area Overlay Kontrol Jendela tidak direkomendasikan. Tindakan ini akan melanggar pedoman desain di macOS, platform yang mengharapkan pengguna melihat menu bar (baik yang disediakan sistem maupun yang kustom) di bagian atas layar.

Jika aplikasi Anda memberikan pengalaman layar penuh, pertimbangkan dengan cermat apakah masuk akal jika Overlay Kontrol Jendela menjadi bagian dari tampilan layar penuh. Anda mungkin ingin menyusun ulang tata letak saat peristiwa onfullscreenchange diaktifkan.

Demo

Saya telah membuat demo yang dapat Anda coba di berbagai browser yang didukung dan tidak didukung serta dalam status terinstal dan tidak terinstal. Untuk pengalaman Overlay Kontrol Jendela yang sebenarnya, Anda perlu menginstal aplikasi. Anda dapat melihat dua screenshot tentang apa yang akan Anda dapatkan di bawah. Kode sumber untuk aplikasi tersedia di Glitch.

Aplikasi demo Konten Unggulan Wikimedia dengan Overlay Kontrol Jendela.
Aplikasi demo tersedia untuk eksperimen.

Fitur penelusuran di overlay kontrol jendela berfungsi sepenuhnya:

Aplikasi demo Konten Unggulan Wikimedia dengan Overlay Kontrol Jendela dan penelusuran aktif untuk istilah &#39;cleopa…&#39; yang menandai salah satu artikel dengan istilah yang cocok &#39;Cleopatra&#39;.
Fitur penelusuran yang menggunakan Overlay Kontrol Jendela.

Pertimbangan keamanan

Tim Chromium mendesain dan menerapkan Window Controls Overlay API menggunakan prinsip inti yang ditentukan dalam Mengontrol Akses ke Fitur Platform Web yang Canggih, termasuk kontrol pengguna, transparansi, dan ergonomi.

Spoofing

Memberi situs kontrol sebagian pada kolom judul memungkinkan developer memalsukan konten di area yang sebelumnya tepercaya dan dikontrol browser. Saat ini, di browser Chromium, mode mandiri menyertakan kolom judul yang saat peluncuran awal menampilkan judul halaman web di sebelah kiri, dan origin halaman di sebelah kanan (diikuti dengan tombol "setelan dan lainnya" serta kontrol jendela). Setelah beberapa detik, teks asal akan menghilang. Jika browser disetel ke bahasa kanan-ke-kiri (RTL), tata letak ini akan dibalik sehingga teks asal berada di sebelah kiri. Tindakan ini akan membuka overlay kontrol jendela untuk memalsukan origin jika tidak ada padding yang cukup antara origin dan tepi kanan overlay. Misalnya, asal "evil.ltd" dapat ditambahkan dengan situs tepercaya "google.com", sehingga pengguna percaya bahwa sumbernya tepercaya. Rencananya adalah mempertahankan teks asal ini agar pengguna mengetahui asal aplikasi dan dapat memastikan bahwa aplikasi tersebut sesuai dengan ekspektasi mereka. Untuk browser yang dikonfigurasi RTL, harus ada padding yang cukup di sebelah kanan teks asal untuk mencegah situs berbahaya menambahkan asal yang tidak aman dengan asal tepercaya.

Pelacakan Sidik Jari

Mengaktifkan overlay kontrol jendela dan area yang dapat ditarik tidak menimbulkan masalah privasi yang signifikan selain deteksi fitur. Namun, karena perbedaan ukuran dan posisi tombol kontrol jendela di berbagai sistem operasi, metode navigator.windowControlsOverlay.getTitlebarAreaRect() menampilkan DOMRect yang posisi dan dimensinya mengungkapkan informasi tentang sistem operasi tempat browser berjalan. Saat ini, developer sudah dapat menemukan OS dari string agen pengguna, tetapi karena masalah sidik jari, ada diskusi tentang membekukan string UA dan menyatukan versi OS. Ada upaya berkelanjutan dalam komunitas browser untuk memahami seberapa sering ukuran overlay kontrol jendela berubah di berbagai platform, karena asumsi saat ini adalah bahwa ukuran ini cukup stabil di berbagai versi OS dan dengan demikian tidak akan berguna untuk mengamati versi OS kecil. Meskipun ini berpotensi menjadi masalah sidik jari, masalah ini hanya berlaku untuk PWA yang diinstal yang menggunakan fitur kolom judul kustom dan tidak berlaku untuk penggunaan browser umum. Selain itu, API navigator.windowControlsOverlay tidak akan tersedia untuk iframe yang disematkan di dalam PWA.

Membuka origin yang berbeda dalam PWA akan menyebabkan PWA kembali ke panel judul mandiri normal, meskipun memenuhi kriteria di atas dan diluncurkan dengan overlay kontrol jendela. Hal ini dilakukan untuk mengakomodasi kolom hitam yang muncul saat navigasi ke origin yang berbeda. Setelah kembali ke origin asli, overlay kontrol jendela akan digunakan lagi.

Kolom URL hitam untuk navigasi lintas origin.
Bar hitam ditampilkan saat pengguna membuka origin yang berbeda.

Masukan

Tim Chromium ingin mengetahui pengalaman Anda dengan Window Controls Overlay API.

Beri tahu kami tentang desain API

Apakah ada sesuatu tentang API yang tidak berfungsi seperti yang Anda harapkan? Atau, apakah ada metode atau properti yang tidak ada dan perlu Anda terapkan untuk mewujudkan ide Anda? Ada pertanyaan atau komentar tentang model keamanan? Laporkan masalah spesifikasi di repo GitHub yang sesuai, atau tambahkan pendapat Anda ke masalah yang sudah ada.

Melaporkan masalah terkait penerapan

Apakah Anda menemukan bug pada penerapan Chromium? Atau apakah implementasinya berbeda dengan spesifikasi? Laporkan bug di new.crbug.com. Pastikan untuk menyertakan detail sebanyak mungkin, petunjuk sederhana untuk mereproduksi, dan masukkan UI>Browser>WebAppInstalls di kotak Komponen.

Menunjukkan dukungan untuk API

Apakah Anda berencana menggunakan Window Controls Overlay API? Dukungan publik Anda membantu tim Chromium memprioritaskan fitur dan menunjukkan kepada vendor browser lain betapa pentingnya dukungan untuk fitur tersebut.

Kirim Tweet ke @ChromiumDev dengan hashtag #WindowControlsOverlay dan beri tahu kami di mana dan bagaimana Anda menggunakannya.

Link bermanfaat

Ucapan terima kasih

Window Controls Overlay diimplementasikan dan ditentukan oleh Amanda Baker dari tim Microsoft Edge. Artikel ini ditinjau oleh Joe Medley dan Kenneth Rohde Christiansen. Gambar utama oleh Sigmund di Unsplash.