src/components/ui/Dropdown.astro
---
/**
* Dropdown
* CSS-only dropdown menu met hover trigger.
*/
interface Props {
label: string;
items: { label: string; href?: string; icon?: string; divider?: boolean }[];
align?: 'left' | 'right';
}
const { label, items, align = 'left' } = Astro.props;
---
<div class="dd">
<button class="dd-trigger" aria-haspopup="true">{label} <span class="dd-arrow" aria-hidden="true">▾</span></button>
<div class={`dd-menu dd-menu--${align}`} role="menu">
{items.map(item => item.divider
? <div class="dd-divider" role="separator"></div>
: (
<a href={item.href || '#'} class="dd-item" role="menuitem">
{item.icon && <span class="dd-item-icon" aria-hidden="true">{item.icon}</span>}
{item.label}
</a>
)
)}
</div>
</div>
<style>
.dd { position: relative; display: inline-block; }
.dd-trigger { padding: 0.5625rem 1rem; background: #fff; border: 1.5px solid #d1d5db; border-radius: 0.5rem; font-size: 0.9375rem; font-weight: 500; color: #374151; cursor: pointer; display: inline-flex; align-items: center; gap: 0.5rem; transition: border-color 0.15s; }
.dd-trigger:hover { border-color: #9ca3af; }
.dd-arrow { font-size: 0.75rem; opacity: 0.6; }
.dd-menu { position: absolute; top: calc(100% + 6px); background: #fff; border: 1px solid #e5e7eb; border-radius: 0.625rem; padding: 0.375rem; min-width: 180px; box-shadow: 0 8px 24px rgba(0,0,0,0.1); z-index: 100; opacity: 0; pointer-events: none; transform: translateY(-4px); transition: opacity 0.15s, transform 0.15s; }
.dd-menu--left { left: 0; }
.dd-menu--right { right: 0; }
.dd:hover .dd-menu, .dd:focus-within .dd-menu { opacity: 1; pointer-events: auto; transform: translateY(0); }
.dd-item { display: flex; align-items: center; gap: 0.625rem; padding: 0.5625rem 0.875rem; font-size: 0.9375rem; color: #374151; border-radius: 0.375rem; text-decoration: none; transition: background 0.1s; }
.dd-item:hover { background: #f3f4f6; color: #0a0a0a; }
.dd-item-icon { font-size: 1rem; }
.dd-divider { height: 1px; background: #f3f4f6; margin: 0.375rem 0; }
</style>
Props
| Prop | Type | Default | Beschrijving |
|---|---|---|---|
label * | string | — | Knoplabel |
items * | { label: string; href?: string; icon?: string; divider?: boolean }[] | — | Menu items |
align | 'left' | 'right' | 'left' | Uitlijning van het menu |
* = verplicht