Composants
DropdownMenu nouveau
Un menu d'actions data-driven : tu décris le bouton déclencheur via
button et la liste d'actions via items. Sections,
séparateurs, sous-menus, items destructifs et descriptions sont tous exprimés en données.
divider, sous-menus items, variante destructive) est déclarée en
données, et Astryx gère l'ouverture, le focus clavier APG et la fermeture.
import { DropdownMenu } from "@forme-ch/ui/controls";
import { PencilSimpleIcon, CopyIcon, TrashIcon } from "@forme-ch/ui/icons";
<DropdownMenu
button={{ label: "Actions", variant: "secondary" }}
hasChevron
items={[
{ label: "Éditer", icon: <PencilSimpleIcon />, onClick: edit },
{ label: "Dupliquer", icon: <CopyIcon />, onClick: duplicate },
{ type: "divider" },
{ label: "Supprimer", icon: <TrashIcon />, variant: "destructive", onClick: remove },
]}
/> Sections et descriptions
Regroupe les actions par section ; un item peut porter une description.
<DropdownMenu
button={{ label: "Facture", variant: "primary", icon: <PencilSimpleIcon /> }}
hasChevron
menuWidth={240}
items={[
{ type: "section", title: "Édition", items: [ { label: "Modifier", onClick: edit } ] },
{ type: "section", title: "Cycle de vie", items: [
{ label: "Archiver", description: "Sort de la liste active", onClick: archive },
{ label: "Supprimer", variant: "destructive", onClick: remove },
] },
]}
/> Ouverture contrôlée
Pilote l'état avec isMenuOpen et onOpenChange (ici via useState).
const [open, setOpen] = useState(false);
<DropdownMenu
button={{ label: "Menu contrôlé", variant: "secondary" }}
hasChevron
isMenuOpen={open}
onOpenChange={setOpen}
items={[{ label: "Option A", onClick: a }, { label: "Option B", onClick: b }]}
/> Props
| Prop | Type | Défaut | Description |
|---|---|---|---|
button * | DropdownTriggerProps | — | Config du bouton déclencheur : { label*, variant?, size?, icon?, iconOnly?, isDisabled? }. iconOnly → isIconOnly côté Astryx. |
items * | DropdownMenuOption[] | — | Items data-driven : { label, icon?, onClick?, isDisabled?, description?, variant?, endContent?, items? }, ou { type: 'divider' }, ou une section { type: 'section', title?, items }. |
hasChevron | boolean | false | Affiche un chevron ▾ à droite du label du déclencheur. |
placement | Placement | — | above · below · start · end. |
alignment | Alignment | — | start · center · end. |
menuWidth | number | string | — | Largeur imposée du panneau du menu. |
isMenuOpen | boolean | — | Ouverture contrôlée. |
onOpenChange | (open: boolean) => void | — | Notifie l'ouverture / fermeture. |
className | string | — | Classe CSS additionnelle. |
style | CSSProperties | — | Styles inline. |
Accessibilité
Le focus clavier suit le pattern APG des menus : ouverture au clic, navigation par flèches,
fermeture sur Échap et sur clic hors zone — géré nativement par Astryx. Un item
iconOnly sur le déclencheur utilise le label comme
nom accessible. Les items destructifs sont signalés visuellement et par leur libellé, pas par la
seule couleur.
Do & Don't
✓ À faire
Grouper les actions liées en section. Isoler l'action destructive après un divider, en variant: "destructive".
✕ À éviter
Empiler dix actions sans hiérarchie. Reconstruire un menu maison avec position: absolute et gestion clavier ad hoc.