Menu
Di halaman ini
Menu adalah sebuah <details> dengan panel bergaya. Itu pilihan yang disengaja ketimbang API popover: popover tinggal di lapisan teratas dan tidak bisa diposisikan terhadap pemicunya tanpa penempatan jangkar, yang belum tersedia di mana-mana. Sebuah <details> memposisikan dirinya dengan benar hari ini dan tidak butuh apa pun dimuat.
Pemicunya adalah <summary> itu, ditata seperti tombol — jadi Anda memberikan labelnya dan props tombolnya ke menu() alih-alih memberikan button() yang sudah dirender. Sebuah summary sudah interaktif, dan tombol di dalamnya menyarangkan dua kendali padahal hanya ada satu tindakan: markup tidak sah, dan dua perhentian tab untuk satu hal.
Penutupan lewat klik di luar dan Escape datang dari penangan ontoggle yang mengimpornya saat sebuah menu pertama kali dibuka — dan hanya saat itu. Jika modul itu tidak pernah datang, menunya tetap membuka dan menutup lewat summary-nya sendiri.
Menu dasar
menu({ trigger: 'Tindakan' },
menuItem({ href: '#edit' }, 'Sunting'),
menuItem({ href: '#duplicate' }, 'Gandakan'),
menuSeparator(),
menuItem({ href: '#delete' }, 'Hapus'),
)Perataan
Menu membuka dari tepi awal pemicunya. align: 'end' membaliknya, dan itulah yang dibutuhkan menu di dekat tepi kanan sebuah bilah.
stack({ direction: 'row', gap: 'xl', justify: 'space-between', style: 'width: 100%' },
menu({ trigger: 'Rata awal', variant: 'soft' },
menuItem({ href: '#a' }, 'Pertama'),
menuItem({ href: '#b' }, 'Kedua'),
),
menu({ trigger: 'Rata akhir', variant: 'soft', align: 'end' },
menuItem({ href: '#c' }, 'Pertama'),
menuItem({ href: '#d' }, 'Kedua'),
),
)Pemicu ikon
Ikon tanpa teks trigger butuh sebuah label — ia menjadi nama yang dapat diakses, yang tidak bisa diberikan ikonnya.
stack({ direction: 'row', gap: 'md' },
menu({
align: 'end',
label: 'Tindakan lainnya',
variant: 'ghost',
icon: icon('more-horizontal'),
},
menuItem({ href: '#rename' }, 'Ganti nama'),
menuItem({ href: '#move' }, 'Pindahkan'),
menuSeparator(),
menuItem({ href: '#archive' }, 'Arsipkan'),
),
)Item dengan ikon
menu({ trigger: 'Berkas' },
menuItem({
href: '#new',
icon: icon('plus'),
}, 'Halaman baru'),
menuItem({
href: '#open',
icon: icon('folder'),
}, 'Buka…'),
menuSeparator(),
menuItem({
href: '#build',
icon: icon('zap'),
}, 'Bangun situs'),
)Tombol alih-alih tautan
Item tanpa href merender sebuah <button> — untuk tindakan yang terjadi di halaman itu, bukan navigasi.
menu({ trigger: 'Ekspor', variant: 'soft', color: 'primary' },
menuItem({ onclick: "import('/su/toast.js').then(m=>m.toast('Diekspor sebagai JSON.',{color:'success'}))" }, 'Sebagai JSON'),
menuItem({ onclick: "import('/su/toast.js').then(m=>m.toast('Diekspor sebagai CSV.',{color:'success'}))" }, 'Sebagai CSV'),
)Di dalam bilah aplikasi
appBar({ brand: 'sitelo' },
appBarSpacer(),
appBarActions(
themeToggle(),
menu({
align: 'end',
label: 'Lainnya',
variant: 'ghost',
icon: icon('more-horizontal'),
},
menuItem({ href: '/docs' }, 'Dokumentasi'),
menuItem({ href: '/examples' }, 'Contoh'),
menuSeparator(),
menuItem({ href: 'https://github.com/paul-browne/sitelo' }, 'GitHub'),
),
),
)Aksesibilitas
Panelnya adalah role="menu" yang itemnya ber-role="menuitem", dan summary-nya membawa aria-haspopup. Sebuah <details> bukan widget menu bawaan, jadi ini pendekatan yang masuk akal, bukan yang sempurna — untuk daftar tautan biasa, sebuah nav di dalam details-nya sama sahnya dan mengklaim lebih sedikit.
Props
menu() — props pemicunya adalah props tombol:
| Prop | Tipe | Bawaan | Deskripsi |
|---|---|---|---|
trigger | Child | — | Label yang terlihat. Berikan teks, bukan button() yang sudah dirender. |
icon | Child | — | Markup sebelum labelnya, atau sendirian untuk pemicu yang hanya berikon. |
label | string | — | Nama yang dapat diakses. Wajib ketika ada ikon dan tidak ada teks pemicu. |
variant | 'solid' | 'soft' | 'outline' | 'ghost' | 'link' | 'outline' | Penataan pemicunya. |
color | 'primary' | 'neutral' | 'success' | 'warning' | 'danger' | 'neutral' | Dari palet mana pemicunya menimba. |
size | 'sm' | 'md' | 'lg' | 'md' | Ukuran pemicunya. |
align | 'start' | 'end' | 'start' | Dengan tepi pemicu yang mana panelnya disejajarkan. |
triggerClass | string | — | Kelas tambahan untuk pemicunya, bukan details pembungkusnya. |
menuItem():
| Prop | Tipe | Bawaan | Deskripsi |
|---|---|---|---|
href | string | — | Merender jangkar; tanpa itu, sebuah tombol. |
icon | Child | — | Markup sebelum labelnya. |
as | string | 'button' | Elemen yang dirender ketika tidak ada href. |
menuSeparator() tidak menerima props — ia adalah garis rambut di antara kelompok item.