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 Membuat PWA terasa lebih seperti aplikasi, Anda mungkin ingat bagaimana saya menyebutkan menyesuaikan panel judul aplikasi sebagai strategi untuk menciptakan pengalaman yang lebih mirip aplikasi. Berikut adalah contoh tampilannya yang menampilkan aplikasi Podcast macOS.

Panel 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 keberatan dengan mengatakan bahwa Podcast adalah aplikasi macOS khusus platform yang tidak berjalan di browser sehingga dapat melakukan apa yang diinginkan tanpa harus mengikuti aturan browser. Memang benar, tetapi kabar baiknya adalah fitur Overlay Kontrol Jendela, yang merupakan topik artikel ini, akan segera memungkinkan Anda membuat antarmuka pengguna yang serupa untuk PWA.

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. Standarisasi properti CSS eksklusif sebelumnya, -webkit-app-region, sebagai properti app-region untuk menentukan area yang dapat ditarik di konten web.
  4. Mekanisme untuk membuat kueri dan mengatasi wilayah kontrol jendela melalui anggota windowControlsOverlay dari window.navigator.

Apa yang dimaksud dengan Overlay Kontrol Jendela

Area panel judul mengacu pada ruang di sebelah kiri atau kanan kontrol jendela (yaitu, tombol untuk memperkecil, memaksimalkan, menutup, dll.) dan sering kali berisi judul aplikasi. Overlay Kontrol Jendela memungkinkan aplikasi web progresif (PWA) memberikan nuansa yang lebih mirip 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 panel judul yang sebelumnya dikontrol browser.

Status saat ini

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

Cara menggunakan Overlay Kontrol Jendela

Menambahkan window-controls-overlay ke manifes aplikasi web

Progressive Web App dapat memilih untuk menggunakan 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 menyertakan "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 panel judul kosong dengan kontrol jendela reguler di sebelah kiri atau kanan, bergantung pada sistem operasi.

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

Memindahkan konten ke panel judul

Setelah 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 panel 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 di screenshot di bawah. Panel judul sepenuhnya responsif. Saat Anda mengubah ukuran jendela PWA, panel judul akan bereaksi seolah-olah terdiri dari konten HTML reguler, yang sebenarnya memang demikian.

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

Menentukan bagian mana dari panel judul yang dapat ditarik

Meskipun screenshot di atas menunjukkan bahwa Anda sudah selesai, Anda belum selesai sepenuhnya. Jendela PWA tidak dapat lagi ditarik (selain area yang sangat kecil), karena tombol kontrol jendela bukan area tarik, dan bagian lain dari panel judul terdiri dari widget penelusuran. Perbaiki hal ini menggunakan properti CSS app-region dengan nilai drag. Dalam kasus konkret, Anda dapat membuat semuanya selain elemen 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 bersifat 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

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

/* 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 panel judul dalam semua situasi. Meskipun tidak akan ada di browser yang tidak mendukung fitur Overlay Kontrol Jendela, fitur ini juga tidak akan ada saat PWA yang dimaksud berjalan di tab. Untuk mendeteksi situasi ini, Anda dapat mengkueri 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

Membuat kueri area overlay kontrol jendela dengan getTitlebarAreaRect() dapat mencukupi untuk hal-hal satu kali seperti menyetel gambar latar belakang yang benar berdasarkan lokasi kontrol jendela, tetapi dalam kasus lain, kontrol yang lebih terperinci diperlukan. Misalnya, kemungkinan kasus penggunaannya adalah menyesuaikan overlay kontrol jendela berdasarkan ruang yang tersedia dan menambahkan lelucon tepat di overlay kontrol jendela jika ada cukup ruang.

Area overlay kontrol jendela di jendela sempit dengan teks yang dipersingkat.
Kontrol panel judul disesuaikan dengan jendela yang 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 tersebut, secara default, HTML yang dibuat untuk overlay kontrol jendela akan ditampilkan secara inline seperti konten HTML biasa dan nilai penggantian variabel env() akan diterapkan untuk pemosisian. 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 overlay melaporkan false, sembunyikan konten HTML tersebut.

PWA yang berjalan di tab browser dengan overlay kontrol jendela yang ditampilkan di isi.
Kontrol yang ditujukan untuk panel judul dapat dengan mudah ditampilkan 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 isi.
Kontrol yang ditujukan untuk panel judul dapat dengan mudah ditampilkan di isi pada browser lama.

Pertimbangan UI

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

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

Demo

Kami telah membuat demo yang dapat Anda gunakan di browser yang mendukung dan tidak mendukung, 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 Andal, termasuk kontrol pengguna, transparansi, dan ergonomi.

Spoofing

Memberikan kontrol sebagian pada kolom judul situs akan memberi developer ruang untuk melakukan spoofing konten di area yang sebelumnya merupakan area tepercaya yang dikontrol browser. Saat ini, di browser Chromium, mode mandiri menyertakan panel judul yang pada peluncuran awal menampilkan judul halaman web di sebelah kiri, dan asal 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 melakukan spoofing origin jika padding antara origin dan tepi kanan overlay tidak memadai. Misalnya, asal "evil.ltd" dapat ditambahkan dengan situs tepercaya "google.com", sehingga pengguna percaya bahwa sumber tersebut tepercaya. Rencananya adalah mempertahankan teks asal ini sehingga 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 origin yang tidak aman dengan origin tepercaya.

Pelacakan Sidik Jari

Mengaktifkan overlay kontrol jendela dan area yang dapat ditarik tidak menimbulkan masalah privasi yang signifikan selain deteksi fitur. Namun, karena ukuran dan posisi tombol kontrol jendela yang berbeda di seluruh sistem operasi, metode navigator.windowControlsOverlay.getTitlebarAreaRect() akan 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 pembekuan string UA dan penyatuan versi OS. Ada upaya berkelanjutan dalam komunitas browser untuk memahami seberapa sering ukuran overlay kontrol jendela berubah di seluruh platform, karena asumsi saat ini adalah bahwa ukuran ini cukup stabil di seluruh versi OS sehingga tidak akan berguna untuk mengamati versi OS minor. Meskipun ini adalah potensi masalah pengambilan sidik jari, masalah ini hanya berlaku untuk PWA terinstal yang menggunakan fitur panel judul kustom dan tidak berlaku untuk penggunaan browser umum. Selain itu, navigator.windowControlsOverlay API tidak akan tersedia untuk iframe yang disematkan di dalam PWA.

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

Panel URL hitam untuk navigasi di luar origin.
Panel hitam ditampilkan saat pengguna membuka asal yang berbeda.

Masukan

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

Ceritakan kepada 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 yang Anda perlukan untuk menerapkan ide Anda? Ada pertanyaan atau komentar tentang model keamanan? Ajukan masalah spesifikasi di repo GitHub yang sesuai, atau tambahkan pendapat Anda ke masalah yang 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 Components. Glitch sangat cocok untuk membagikan rekaman ulang yang cepat dan mudah.

Menampilkan 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 mendukung fitur tersebut.

Kirim Tweet ke @ChromiumDev dengan hashtag #WindowControlsOverlay dan beri tahu kami tempat dan cara 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 hero oleh Sigmund di Unsplash.