Menyesuaikan overlay kontrol jendela pada kolom judul PWA Anda

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

Jika Anda ingat artikel saya Membuat PWA terasa lebih seperti aplikasi, Anda mungkin ingat bagaimana saya menyebutkan menyesuaikan panel judul aplikasi Anda sebagai strategi untuk menciptakan pengalaman yang lebih mirip aplikasi. Berikut adalah contoh tampilan yang menunjukkan aplikasi Podcast macOS.

Kolom judul aplikasi Podcast macOS yang menampilkan tombol kontrol media dan metadata tentang podcast yang sedang diputar.
Kolom 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, sehingga dapat melakukan apa yang diinginkannya tanpa harus mengikuti aturan browser. Benar, tetapi kabar baiknya adalah fitur Overlay Kontrol Jendela, yang merupakan topik artikel ini, 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" di 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 eksklusif sebagai properti app-region untuk menentukan region yang dapat ditarik di konten web.
  4. Mekanisme untuk mengkueri dan menangani region kontrol jendela melalui anggota windowControlsOverlay dari window.navigator.

Apa itu Overlay Kontrol Jendela

Area panel judul mengacu pada ruang di sebelah kiri atau kanan kontrol jendela (yaitu, tombol untuk meminimalkan, memaksimalkan, menutup, dll.) dan sering berisi judul aplikasi. Overlay Window Controls memungkinkan progressive web application (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 yang sebelumnya merupakan area panel judul yang dikontrol browser.

Status saat ini

Langkah Status
1. Buat pesan penjelasan Selesai
2. Membuat draf awal spesifikasi Selesai
3. Mengumpulkan masukan & mengulangi desain Dalam proses
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 saat semua kondisi berikut terpenuhi:

  1. Aplikasi tidak dibuka di browser, tetapi di jendela PWA terpisah.
  2. Manifes menyertakan "display_override": ["window-controls-overlay"]. (Setelah itu, nilai lainnya akan diizinkan.)
  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 operasinya.

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

Karena sekarang ada ruang di bilah judul, Anda dapat memindahkan sesuatu ke sana. Untuk artikel ini, saya membuat {i>PWA<i} 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 panel judul, diperlukan beberapa 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);
}

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

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

Menentukan bagian mana dari bilah judul yang dapat ditarik

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

Sejauh ini, kode memiliki satu masalah: pada beberapa platform, kontrol jendela berada di sebelah kanan, sedangkan di platform lain, kontrol jendela berada di sebelah kiri. Lebih parah lagi, menu Chrome "tiga titik" juga akan berubah posisi, berdasarkan platform. Artinya, gambar latar gradien linear perlu diadaptasi secara dinamis untuk dijalankan dari #131313maroon atau maroon#131313maroon, agar 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 dalam aturan CSS class .search secara langsung (seperti sebelumnya), kode yang dimodifikasi kini menggunakan dua class yang ditetapkan oleh 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

Dalam situasi apa pun, overlay kontrol jendela tidak akan terlihat di area panel judul. Meskipun secara alami tidak akan ada di browser yang tidak mendukung fitur Overlay Kontrol Jendela, fitur tersebut 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

Mengkueri area overlay kontrol jendela dengan getTitlebarAreaRect() sudah cukup untuk melakukan tindakan satu kali, seperti menyetel gambar latar yang benar berdasarkan lokasi kontrol jendela, tetapi dalam kasus lain, diperlukan kontrol yang lebih terperinci. Misalnya, kemungkinan kasus penggunaan adalah menyesuaikan overlay kontrol jendela berdasarkan ruang yang tersedia dan menambahkan lelucon tepat di overlay kontrol jendela saat ada cukup ruang.

Area overlay kontrol jendela di 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 ini. Anda dapat membaca perbedaan antara keduanya di MDN.

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

Kompatibilitas saat dijalankan di tab dan di browser yang tidak didukung

Ada dua kemungkinan kasus yang dapat dipertimbangkan:

  • Kasus saat aplikasi berjalan di browser yang mendukung Overlay Kontrol Jendela, tetapi tempat 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 inline seperti konten HTML reguler dan nilai penggantian variabel env() akan digunakan 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 melaporkan false, maka menyembunyikan konten HTML tersebut.

PWA yang berjalan di tab browser dengan overlay kontrol jendela ditampilkan di bagian isi.
Kontrol yang dimaksudkan untuk panel judul dapat ditampilkan dengan mudah dalam isi di 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 kemungkinan nilai berikutnya sesuai dengan rantai penggantian, misalnya, "standalone".

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

Pertimbangan UI

Meskipun mungkin menarik, membuat menu {i>dropdown<i} klasik di area Overlay Kontrol Jendela tidak disarankan. Tindakan ini akan melanggar pedoman desain di macOS, platform yang memungkinkan pengguna mengharapkan panel menu (baik yang disediakan sistem maupun yang kustom) di bagian atas layar.

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

Demo

Saya telah membuat demo yang dapat Anda gunakan di berbagai browser pendukung dan tidak mendukung, serta dalam status terinstal dan tidak diinstal. Untuk pengalaman Overlay Kontrol Jendela yang sebenarnya, Anda harus menginstal aplikasi. Anda dapat melihat dua screenshot dari tampilan di bawah ini. 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 penuh:

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

Pertimbangan keamanan

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

{i>Spoofing<i}

Dengan memberi situs kontrol sebagian panel judul, developer dapat melakukan spoofing pada konten di wilayah yang sebelumnya merupakan wilayah tepercaya yang dikontrol browser. Saat ini, di browser Chromium, mode mandiri mencakup panel judul yang saat peluncuran awal menampilkan judul halaman di sebelah kiri, dan asal halaman di sebelah kanan (diikuti dengan tombol "setelan dan lainnya" serta kontrol jendela). Setelah beberapa detik, teks asal akan hilang. 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 pada asal, jika tidak ada padding yang cukup antara tempat asal dan tepi kanan overlay. Misalnya, origin "evil.ltd" dapat ditambahkan dengan situs tepercaya "google.com", sehingga pengguna percaya bahwa sumber tersebut dapat dipercaya. Rencananya adalah mempertahankan teks asal ini agar pengguna mengetahui asal aplikasi tersebut dan dapat memastikan bahwa teks tersebut sesuai dengan ekspektasi mereka. Untuk browser yang dikonfigurasi RTL, harus ada padding yang cukup di sebelah kanan teks origin untuk mencegah situs berbahaya menambahkan origin yang tidak aman dengan origin tepercaya.

Pelacakan sidik jari

Mengaktifkan overlay kontrol jendela dan wilayah 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() menampilkan DOMRect yang posisi dan dimensinya mengungkapkan informasi tentang sistem operasi yang digunakan browser untuk berjalan. Saat ini, developer dapat menemukan OS dari string agen pengguna, tetapi karena masalah pelacakan sidik jari, ada diskusi tentang membekukan string UA dan menyatukan versi OS. Ada upaya yang sedang berlangsung dalam komunitas browser untuk memahami seberapa sering ukuran jendela kontrol overlay berubah di seluruh platform, karena asumsi saat ini adalah bahwa perubahan ini cukup stabil di seluruh versi OS sehingga tidak akan berguna untuk mengamati versi OS minor. Meskipun ini merupakan potensi masalah sidik jari, hal 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 bilah hitam yang muncul di navigasi ke asal yang berbeda. Setelah kembali ke asal asli, overlay kontrol jendela akan digunakan lagi.

Kolom URL berwarna hitam untuk navigasi di luar asal.
Batang hitam akan ditampilkan saat pengguna membuka situs asal yang berbeda.

Masukan

Tim Chromium ingin mengetahui pengalaman Anda saat menggunakan 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 hilang yang Anda butuhkan untuk menerapkan ide Anda? Punya 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 implementasi Chromium? Atau apakah implementasinya berbeda dari 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 berfungsi dengan baik untuk berbagi repro yang cepat dan mudah.

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 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 diterapkan dan ditentukan oleh Amanda Baker dari tim Microsoft Edge. Artikel ini ditinjau oleh Joe Medley dan Kenneth Rohde Christiansen. Banner besar oleh Sigmund di Unsplash.