Lompat ke konten

Menu tekan lama

Untuk tiga atau empat aksi yang hanya milik satu baris, dibuka di tempat alih-alih di layar tersendiri.

Tombol dan aksi

Pratinjau langsung

Sumber

<div class="dc-lp">
  <details class="dc-lp__box">
    <summary class="dc-lp__item">
      <span class="dc-lp__name">현장 점검 보고서.pdf</span>
      <span class="dc-lp__meta">2.4MB · 어제 오후 5:12</span>
    </summary>
    <div class="dc-lp__menu" role="group" aria-label="파일 동작">
      <button class="dc-lp__act" type="button">이름 바꾸기</button>
      <button class="dc-lp__act" type="button">공유</button>
      <button class="dc-lp__act dc-lp__act--danger" type="button">삭제</button>
    </div>
  </details>
  <p class="dc-lp__hint">길게 누르면 열립니다. 짧게 눌러도 같은 메뉴가 열려 누구나 닿을 수 있습니다.</p>
</div>
.dc-lp {
  padding: var(--dc-4);
  background: var(--dc-bg);
  font-family: var(--dc-font);
}
.dc-lp__box {
  border: 1px solid var(--dc-line);
  border-radius: var(--dc-r-md);
  background: var(--dc-surface);
  box-shadow: var(--dc-sh-1);
}
.dc-lp__item {
  display: flex;
  flex-direction: column;
  gap: var(--dc-1);
  min-height: 44px;
  padding: var(--dc-3) var(--dc-4);
  border-radius: var(--dc-r-md);
  list-style: none;
  cursor: pointer;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
}
.dc-lp__item::-webkit-details-marker { display: none; }
.dc-lp__item::marker { content: ""; }
.dc-lp__box[open] .dc-lp__item {
  border-bottom: 1px solid var(--dc-line);
  border-radius: var(--dc-r-md) var(--dc-r-md) 0 0;
  background: var(--dc-sunken);
}
.dc-lp__name {
  font-size: 15px;
  font-weight: 600;
  color: var(--dc-text);
}
.dc-lp__meta {
  font-size: 12px;
  color: var(--dc-text-mute);
}
.dc-lp__menu {
  display: flex;
  flex-direction: column;
  padding: var(--dc-1);
}
.dc-lp__act {
  display: flex;
  align-items: center;
  gap: var(--dc-3);
  min-height: 48px;
  padding: 0 var(--dc-3);
  border: 0;
  border-radius: var(--dc-r-sm);
  background: none;
  color: var(--dc-text);
  font-family: var(--dc-font);
  font-size: 15px;
  text-align: left;
  cursor: pointer;
  transition: background var(--dc-fast);
}
.dc-lp__act:hover { background: var(--dc-sunken); }
.dc-lp__act--danger { color: var(--dc-danger); }
.dc-lp__ico {
  width: 20px;
  height: 20px;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.dc-lp__hint {
  margin: var(--dc-3) 0 0;
  font-size: 12px;
  line-height: 1.6;
  color: var(--dc-text-mute);
}
document.querySelectorAll('.dc-lp__box').forEach(function (box) {
  var item = box.querySelector('.dc-lp__item');
  if (!item) return;
  var timer = null;
  function clear() {
    if (timer) { clearTimeout(timer); timer = null; }
  }
  item.addEventListener('pointerdown', function () {
    clear();
    timer = setTimeout(function () {
      timer = null;
      box.open = true;
    }, 450);
  });
  ['pointerup', 'pointercancel', 'pointerleave'].forEach(function (name) {
    item.addEventListener(name, clear);
  });
});

Cara memakainya

  • Kumpulkan hanya aksi milik item itu; aksi selingkup layar taruh di bilah atas
  • Letakkan aksi berisiko paling bawah dan bedakan warnanya agar jari tak menyenggolnya
  • Biarkan item itu tetap terlihat di atas menu agar jelas aksi ini untuk apa

Hal yang perlu diwaspadai

  • Tekan lama tidak terlihat: buat tekan singkat juga membuka, atau sediakan tombol lainnya
  • Dibangun di atas details/summary, menu tetap terbuka saat skrip gagal — skrip hanya menambah tekan lama
  • Beri tiap baris menu tinggi sekitar 48px; baris berdempet memicu salah tekan

Berikutnya