Menu overlay
Tempat tindakan tambahan satu baris, ketika jumlahnya terlalu banyak untuk dipasang sebagai tombol.
Pratinjau langsung
Sumber
<div class="dc-mo">
<details class="dc-mo__root" open>
<summary class="dc-mo__trigger"><svg viewBox="0 0 16 16" aria-hidden="true" focusable="false"><circle cx="8" cy="3" r="1.4" /><circle cx="8" cy="8" r="1.4" /><circle cx="8" cy="13" r="1.4" /></svg><span class="dc-sr">주문 20260907-118 메뉴 열기</span></summary>
<div class="dc-mo__pop" role="menu" aria-label="주문 메뉴">
<button class="dc-mo__item" type="button" role="menuitem"><span class="dc-mo__label">이름 바꾸기</span><kbd class="dc-mo__key">F2</kbd></button>
<button class="dc-mo__item" type="button" role="menuitem"><span class="dc-mo__label">복제하기</span><kbd class="dc-mo__key">Ctrl D</kbd></button>
<hr class="dc-mo__sep">
<div role="group" aria-labelledby="dc-mo-send">
<p class="dc-mo__head" id="dc-mo-send">보내기</p>
<button class="dc-mo__item" type="button" role="menuitem"><span class="dc-mo__label">링크 복사</span></button>
<button class="dc-mo__item" type="button" role="menuitem"><span class="dc-mo__label">엑셀로 내려받기</span></button>
</div>
<hr class="dc-mo__sep">
<button class="dc-mo__item dc-mo__item--danger" type="button" role="menuitem"><span class="dc-mo__label">주문 지우기</span><kbd class="dc-mo__key">Del</kbd></button>
</div>
</details>
</div>
.dc-mo { display: flex; align-items: flex-start; justify-content: flex-end; min-height: 340px; font-family: var(--dc-font); }
.dc-mo--up { align-items: flex-end; }
.dc-mo__root { position: relative; }
.dc-mo__trigger {
display: grid; place-items: center; width: 40px; height: 40px;
border: 1px solid var(--dc-line-field); border-radius: var(--dc-r-sm);
background: var(--dc-surface); color: var(--dc-text);
list-style: none; cursor: pointer;
transition: background var(--dc-fast);
}
.dc-mo__trigger::-webkit-details-marker { display: none; }
.dc-mo__trigger:hover { background: var(--dc-sunken); }
.dc-mo__trigger svg { width: 16px; height: 16px; fill: currentColor; }
.dc-mo__pop {
position: absolute; top: calc(100% + var(--dc-1)); right: 0; z-index: 5;
min-width: 240px; padding: var(--dc-2);
background: var(--dc-surface);
border: 1px solid var(--dc-line); border-radius: var(--dc-r-md);
box-shadow: var(--dc-sh-2);
}
.dc-mo__pop--up { top: auto; bottom: calc(100% + var(--dc-1)); }
.dc-mo__head {
margin: 0; padding: var(--dc-2) var(--dc-2) var(--dc-1);
font-size: 12px; font-weight: 700; color: var(--dc-text-mute);
}
.dc-mo__item {
display: flex; align-items: center; gap: var(--dc-3);
width: 100%; min-height: 40px; padding: 0 var(--dc-2);
border: 0; border-radius: var(--dc-r-xs);
background: transparent; color: var(--dc-text);
font-family: inherit; font-size: 14px; text-align: left;
transition: background var(--dc-fast);
}
.dc-mo__item:hover { background: var(--dc-sunken); }
.dc-mo__item--danger { color: var(--dc-danger); }
.dc-mo__item--danger:hover { background: var(--dc-danger-soft); }
.dc-mo__label { flex: 1 1 auto; }
.dc-mo__key {
flex: none; padding: 1px var(--dc-1);
border: 1px solid var(--dc-line); border-radius: var(--dc-r-xs);
background: var(--dc-sunken); color: var(--dc-text-sub);
font-family: var(--dc-mono); font-size: 11px;
}
.dc-mo__sep { height: 1px; margin: var(--dc-2) 0; border: 0; background: var(--dc-line); }
.dc-mo__sub { position: relative; }
.dc-mo__subtrigger {
display: flex; align-items: center; gap: var(--dc-3);
min-height: 40px; padding: 0 var(--dc-2);
border-radius: var(--dc-r-xs); color: var(--dc-text);
font-size: 14px; list-style: none; cursor: pointer;
transition: background var(--dc-fast);
}
.dc-mo__subtrigger::-webkit-details-marker { display: none; }
.dc-mo__subtrigger:hover { background: var(--dc-sunken); }
.dc-mo__caret { flex: none; color: var(--dc-text-mute); font-size: 11px; }
.dc-mo__subpop {
position: absolute; top: calc(-1 * var(--dc-2)); right: calc(100% + var(--dc-2));
z-index: 6; min-width: 200px; padding: var(--dc-2);
background: var(--dc-surface);
border: 1px solid var(--dc-line); border-radius: var(--dc-r-md);
box-shadow: var(--dc-sh-2);
}
@media (max-width: 420px) {
.dc-mo__pop { min-width: 0; width: calc(100vw - var(--dc-7)); }
.dc-mo__subpop { position: static; right: auto; min-width: 0; margin-top: var(--dc-1); box-shadow: none; }
}
Cara memakainya
- Biarkan satu dua tindakan harian di luar, sisanya masuk ke menu
- Pisahkan yang merusak di bagian bawah dengan garis
- Kalau di bawah pemicunya tidak ada ruang, balik menu agar terbuka ke atas
- Bila pemicunya hanya ikon, nama di dc-sr menyebut ini menu milik apa
Hal yang perlu diwaspadai
- Tombol panah harus bisa berpindah antar item — jangan biarkan Tab jadi satu-satunya jalan
- Submenu cukup satu tingkat, dan di layar sentuh lebih enak dibentangkan di tempat