Composant · Overlay
MenuPopover
StablePanneau flottant ancré à un déclencheur externe, positionné en absolu d'après le rectangle du déclencheur. Il gère le placement, la fermeture au clic extérieur et sur Escape, et recalcule sa position au scroll et au resize. Combiné à MenuTriggerButton + Menu, il forme un menu d'actions ancré complet.
Quand l'utiliser
- Ancrer un Menu (ou tout contenu) à un bouton, avec fermeture extérieure et Escape intégrées.
- Quand le déclencheur et le panneau ne partagent pas le même parent positionné.
- Pour un détail simple inline sans ancrage externe, préférez Popover.
Quand ne pas l'utiliser
- Pour une décision bloquante : utilisez Modal.
- Pour un workflow secondaire long : utilisez Drawer.
- Pour un menu de débordement clé en main : OverflowMenu intègre déjà déclencheur et panneau.
Exemples
MenuPopover + Menu
- Édition
- Distribuer
Voir le code (Svelte)
<OverflowMenu
open
placement="bottom-start"
label="Actions"
triggerLabel="Actions"
items={[{"kind":"group","label":"Édition"},{"value":"edit","label":"Éditer","icon":"✎"},{"value":"duplicate","label":"Dupliquer","icon":"⎘"},{"kind":"divider"},{"kind":"group","label":"Distribuer"},{"value":"share","label":"Partager","icon":"↗"},{"value":"archive","label":"Archiver","icon":"⊟"},{"kind":"divider"},{"value":"delete","label":"Supprimer","danger":true,"icon":"✕"}]}
/>Sur la page réelle, MenuTriggerButton ouvre/ferme le panneau ancré et le choix d'une action le referme. La démo le montre figé ouvert.
Note de parité : le composant Svelte est canonique et porte toute la logique interactive (positionnement absolu via getBoundingClientRect, recalcul au scroll/resize, fermeture au clic extérieur et sur Escape). Les rendus React et Vue sont une variante présentationnelle statique : ils rendent le déclencheur dans le panneau, exposent une prop items et le rôle dialog + aria-label, mais n'implémentent pas le positionnement ni les props align/closeOnOutside/closeOnEscape.
Placements
Voir le code (Svelte)
<div class="docs-demo-stack">
<OverflowMenu
open
placement="bottom-start"
label="bottom-start"
triggerLabel="bottom-start"
items={[{"value":"a","label":"Option A"},{"value":"b","label":"Option B"},{"value":"c","label":"Option C"}]}
/>
<OverflowMenu
open
placement="bottom-end"
label="bottom-end"
triggerLabel="bottom-end"
items={[{"value":"a","label":"Option A"},{"value":"b","label":"Option B"},{"value":"c","label":"Option C"}]}
/>
<OverflowMenu
open
placement="top-start"
label="top-start"
triggerLabel="top-start"
items={[{"value":"a","label":"Option A"},{"value":"b","label":"Option B"},{"value":"c","label":"Option C"}]}
/>
<OverflowMenu
open
placement="top-end"
label="top-end"
triggerLabel="top-end"
items={[{"value":"a","label":"Option A"},{"value":"b","label":"Option B"},{"value":"c","label":"Option C"}]}
/>
</div>Les quatre placements (bottom-start, bottom-end, top-start, top-end), tous figés ouverts.
Anatomie
- Déclencheur : élément externe référencé par la prop trigger (HTMLElement).
- Panneau (.st-menuPopover, role="dialog") : surface flottante positionnée en absolu.
- Contenu : fourni via children, typiquement un Menu dont il partage la surface visuelle.
- Modificateurs de placement (--bottom-start, --top-end…) et d'alignement (--alignEnd, --alignCenter).
Accessibilité
- Le panneau a role="dialog" et un aria-label fourni par la prop label.
- closeOnEscape ferme sur Escape ; closeOnOutside ferme au clic ou pointeur extérieur.
- Câblez aria-haspopup et aria-expanded sur le déclencheur (MenuTriggerButton le fait via expanded).
- La détection du clic extérieur traverse le shadow DOM via composedPath.
Lignes directrices
À faire
- Lier le déclencheur au panneau via la même variable open (bind:open).
- Choisir le placement selon l'espace disponible autour du déclencheur.
À éviter
- Oublier de fournir un trigger : le positionnement en dépend.
- Y loger un long workflow : préférez Drawer ou une page.
API
| Prop | Type | Défaut | Description |
|---|---|---|---|
open | boolean (bindable) | false | Affiche le panneau. |
trigger | HTMLElement | null | requis | Élément servant d'ancre au positionnement. |
placement | "bottom-start" | "bottom-end" | "top-start" | "top-end" | "bottom-start" | Position du panneau par rapport au déclencheur. |
align | "start" | "end" | "center" | dérivé du placement | Surcharge l'alignement horizontal. |
label | string | requis | aria-label du panneau. |
closeOnOutside | boolean | true | Ferme au clic/pointeur extérieur. |
closeOnEscape | boolean | true | Ferme sur Escape. |
children | Snippet | optionnel | Contenu du panneau. |
class | string | optionnel | Classe(s) sur le panneau. |
| Autres attributs | HTMLAttributes<HTMLDivElement> | N/A | Propagés sur le <div> panneau. |
Le composant se positionne en absolu via getBoundingClientRect() sur le déclencheur et recalcule sa position lors du scroll et du resize de la fenêtre.
Tokens utilisés
--st-component-menu-background--st-component-menu-border--st-component-menu-radius--st-component-menu-text--st-component-menu-shadow--st-component-menu-minWidth--st-component-menu-maxWidth--st-component-popover-zIndex