Context menu
Un menu d’actions au clic droit ou à l’appui long, avec sous-menus, éléments case à cocher et radio, et retour visuel de maintien au toucher.
Last action: Nothing yet
pnpm dlx shadcn@latest add https://hextaui.com/r/context-menu.jsonAjoute le composant, les tokens de thème HextaUI et les composants HextaUI dont il dépend.
Ajoutez les tokens de thème à votre CSS global, si ce n’est pas déjà fait.
Installez les dépendances.
pnpm add @base-ui/react @tabler/icons-react class-variance-authority cnCopiez et collez le code suivant dans votre projet.
components/ui/context-menu.tsx Mettez à jour les chemins d’import selon la configuration de votre projet.
Liste de fichiers
Donnez à chaque ligne son propre menu. La ligne ouverte reste en surbrillance, et un élément destructeur passe la main à une boîte de dialogue d’alerte pour confirmation.
Contrôlé
Passez open et onOpenChange pour gérer l’état. Le deuxième argument indique pourquoi il a changé, par exemple trigger-press, outside-press ou escape-key. Les éléments avec closeOnClick={false} le gardent ouvert.
Désactivé
Un <ContextMenu /> désactivé rend la zone au menu propre du navigateur. Les éléments désactivés restent visibles mais sont ignorés par le clavier.
Retour d’appui long
Sur écran tactile, le menu s’ouvre après un appui long. Tant que le doigt reste appuyé, la zone rétrécit légèrement pour indiquer que l’appui est pris en compte. Déplacer le doigt l’annule. Définissez holdFeedback={false} pour le désactiver.
Contenu long
Les libellés longs passent à la ligne dans une largeur maximale de 20 rem, et les menus hauts défilent dans l’espace restant du viewport.
Sous-menus imbriqués
Les sous-menus s’ouvrent au survol ou avec les flèches, à n’importe quelle profondeur. Un déclencheur de sous-menu désactivé ne s’ouvre jamais.
Dans une sheet
Le menu se superpose aux autres surcouches, et Escape ne ferme que le menu, pas la sheet derrière lui.
Rendre comme un autre élément
Utilisez render pour faire du déclencheur n’importe quel élément, comme une figure, ou pour transformer un élément en lien.
De droite à gauche
Le menu lit la direction du déclencheur : les sous-menus s’ouvrent donc à gauche et les flèches s’inversent.
| Touche | Action |
|---|---|
| ↓ | Met en évidence l’élément suivant, en rebouclant à la fin. |
| ↑ | Met en évidence l’élément précédent, en rebouclant au début. |
| Home | Met en évidence le premier élément. |
| End | Met en évidence le dernier élément. |
| EnterSpace | Exécute l’élément en surbrillance. Les éléments à case à cocher et radio basculent et gardent le menu ouvert. |
| → | Ouvre le sous-menu en surbrillance et s’y déplace. ← dans les mises en page de droite à gauche. |
| ← | Ferme le sous-menu actuel et revient à son déclencheur. → dans les mises en page de droite à gauche. |
| Esc | Ferme le menu actuel. Dans un sous-menu, seul ce sous-menu se ferme. |
| A–Z | Met en évidence l’élément suivant commençant par cette lettre. |
- Un menu contextuel est un raccourci. Rendez chaque action qu’il contient accessible d’une autre manière aussi, comme un bouton visible ou un menu déroulant, car beaucoup de gens ne font jamais de clic droit ni d’appui long.
- Les navigateurs déclenchent aussi l’événement de menu contextuel pour Shift F10 et la touche Menu sur un élément ayant le focus : un élément focusable dans le déclencheur permet donc aux utilisateurs du clavier de l’ouvrir.
- Les raccourcis dans
<ContextMenuShortcut />ne sont que des libellés. Associez les touches vous-même. - Avec la réduction des animations, le retour d’appui long et le clignotement des éléments sont ignorés et le menu ne fait que se fondre.
Construit sur le menu contextuel de Base UI. Chaque partie accepte les props de la primitive qu’elle enveloppe, ainsi qu’un className fonction qui reçoit l’état de la partie.
| Prop | Type | Par défaut |
|---|---|---|
open | boolean | – |
defaultOpen | boolean | false |
onOpenChangedetails.reason indique la cause du changement. | (open: boolean, details) => void | – |
onOpenChangeCompleteS’exécute à la fin de l’animation d’ouverture ou de fermeture. | (open: boolean) => void | – |
disabledAffiche à la place le menu natif du navigateur. | boolean | false |
loopFocusReboucle la navigation aux flèches aux extrémités. | boolean | true |
highlightItemOnHover | boolean | true |
actionsRefFerme le menu de façon impérative. | RefObject<{ close, unmount }> | – |
| Prop | Type | Par défaut |
|---|---|---|
holdFeedbackRéduit légèrement la zone pendant un appui long sur écran tactile. | boolean | true |
render | ReactElement | (props, state) => ReactElement | <div> |
| Attribut | Description |
|---|---|
data-slot="context-menu-trigger" | Ciblez le déclencheur en CSS. |
data-popup-open | Présent tant que son menu est ouvert. |
data-holding | Présent pendant un appui long. |
data-pressed | Présent tant que le déclencheur est enfoncé. |
| Prop | Type | Par défaut |
|---|---|---|
sideCôté préféré, par rapport au pointeur. | "top" | "right" | "bottom" | "left" | "inline-start" | "inline-end" | "bottom" |
align | "start" | "center" | "end" | "start" |
sideOffset | number | 0 |
alignOffset | number | 0 |
collisionPaddingEspace à conserver entre le menu et les bords du viewport. | number | { top, right, bottom, left } | – |
collisionAvoidanceComment le menu se retourne ou se décale lorsqu’il déborderait. | CollisionAvoidance | – |
anchorSe positionne par rapport à autre chose que le pointeur. | Element | VirtualElement | RefObject | – |
finalFocusOù va le focus après la fermeture du menu. | boolean | RefObject | (closeType) => HTMLElement | boolean | – |
render | ReactElement | (props, state) => ReactElement | <div> |
| Attribut | Description |
|---|---|
data-slot="context-menu-content" | La popup du menu. |
data-open | Présent tant que l’élément est ouvert. |
data-starting-style | Présent pendant l’animation d’entrée du menu. |
data-ending-style | Présent pendant l’animation de sortie du menu. |
data-side | Le côté sur lequel il a été placé après les collisions. |
data-chosen | Présent après le clic sur un élément. Le fondu de sortie attend le clignotement. |
--transform-origin | Le point d’où part l’animation d’agrandissement. |
--available-height | Espace restant dans le viewport. Plafonne la hauteur du menu. |
| Prop | Type | Par défaut |
|---|---|---|
variant | "default" | "destructive" | "default" |
insetDécale le libellé pour l’aligner avec les éléments à case à cocher. | boolean | false |
onClickS’exécute au clic, sur Enter ou Space. Le menu se ferme après un court clignotement. | (event) => void | – |
closeOnClick | boolean | true |
disabled | boolean | false |
labelTexte utilisé pour la recherche à la frappe lorsque les enfants ne sont pas du texte simple. | string | – |
render | ReactElement | (props, state) => ReactElement | <div> |
| Attribut | Description |
|---|---|
data-slot="context-menu-item" | Ciblez les items en CSS. |
data-variant | La variante actuelle. |
data-highlighted | Présent sur l’élément sous le pointeur ou ayant le focus clavier. |
data-disabled | Présent lorsque l’item est désactivé. |
data-inset | Présent lorsque inset est défini. |
data-chosen | Présent sur l’élément cliqué pendant son clignotement. |
| Prop | Type | Par défaut |
|---|---|---|
checked | boolean | – |
defaultChecked | boolean | false |
onCheckedChange | (checked: boolean, details) => void | – |
closeOnClick | boolean | false |
inset | boolean | false |
disabled | boolean | false |
render | ReactElement | (props, state) => ReactElement | <div> |
| Attribut | Description |
|---|---|
data-slot="context-menu-checkbox-item" | Ciblez les éléments à case à cocher en CSS. |
data-checked | Présent lorsqu’il est coché. |
data-unchecked | Présent lorsqu’il est décoché. |
data-highlighted | Présent sur l’élément sous le pointeur ou ayant le focus clavier. |
data-disabled | Présent lorsque l’item est désactivé. |
data-inset | Présent lorsque inset est défini. |
data-chosen | Présent sur l’élément cliqué pendant son clignotement. |
| Prop | Type | Par défaut |
|---|---|---|
value | any | – |
defaultValue | any | – |
onValueChange | (value: any, details) => void | – |
disabled | boolean | false |
| Prop | Type | Par défaut |
|---|---|---|
value | any | – |
closeOnClick | boolean | false |
inset | boolean | false |
disabled | boolean | false |
render | ReactElement | (props, state) => ReactElement | <div> |
| Attribut | Description |
|---|---|
data-slot="context-menu-radio-item" | Ciblez les éléments radio en CSS. |
data-checked | Présent lorsqu’il est sélectionné. |
data-highlighted | Présent sur l’élément sous le pointeur ou ayant le focus clavier. |
data-disabled | Présent lorsque l’item est désactivé. |
data-inset | Présent lorsque inset est défini. |
data-chosen | Présent sur l’élément cliqué pendant son clignotement. |
| Prop | Type | Par défaut |
|---|---|---|
inset | boolean | false |
render | ReactElement | (props, state) => ReactElement | <div> |
Dans <ContextMenuGroup /> ou <ContextMenuRadioGroup />, il étiquette le groupe pour les technologies d’assistance. Ailleurs, c’est un simple titre.
| Prop | Type | Par défaut |
|---|---|---|
open | boolean | – |
defaultOpen | boolean | false |
onOpenChange | (open: boolean, details) => void | – |
disabled | boolean | false |
closeParentOnEscFerme tout le menu avec Escape, et pas seulement ce sous-menu. | boolean | false |
| Prop | Type | Par défaut |
|---|---|---|
inset | boolean | false |
openOnHover | boolean | true |
delayMillisecondes de survol avant l’ouverture du sous-menu. | number | 100 |
closeDelay | number | 0 |
disabled | boolean | false |
render | ReactElement | (props, state) => ReactElement | <div> |
| Attribut | Description |
|---|---|
data-slot="context-menu-sub-trigger" | Ciblez les déclencheurs de sous-menu en CSS. |
data-popup-open | Présent tant que son sous-menu est ouvert. |
data-highlighted | Présent pendant la mise en surbrillance. |
data-disabled | Présent lorsque l’élément est désactivé. |
| Prop | Type | Par défaut |
|---|---|---|
sideS’ouvre par défaut vers la fin de la ligne. | "top" | "right" | "bottom" | "left" | "inline-start" | "inline-end" | – |
align | "start" | "center" | "end" | – |
sideOffset | number | 0 |
alignOffset | number | -4 |
collisionPaddingEspace à conserver entre le menu et les bords du viewport. | number | { top, right, bottom, left } | – |
collisionAvoidanceComment le menu se retourne ou se décale lorsqu’il déborderait. | CollisionAvoidance | – |
anchorSe positionne par rapport à autre chose que le pointeur. | Element | VirtualElement | RefObject | – |
render | ReactElement | (props, state) => ReactElement | <div> |
| Attribut | Description |
|---|---|
data-slot="context-menu-sub-content" | La popup du sous-menu. Prend les mêmes attributs d’état que le menu. |
| Prop | Type | Par défaut |
|---|---|---|
dirGarde les raccourcis comme ⇧⌘S dans l’ordre dans les menus de droite à gauche. | "ltr" | "rtl" | "ltr" |
| Attribut | Description |
|---|---|
data-slot="context-menu-shortcut" | Le libellé du raccourci. |
<ContextMenuGroup /> regroupe des éléments liés sous un libellé. <ContextMenuSeparator /> trace un séparateur. Les deux acceptent render et className, et portent context-menu-group et context-menu-separator comme data-slot.
- Alert dialogUne boîte de dialogue de confirmation pour les actions destructrices ou importantes, qui attend le travail asynchrone et devient une bottom sheet sur mobile.
- CommandUne liste d’actions recherchable, intégrée ou en palette ⌘K, avec pages, raccourcis et correspondances surlignées.
- DialogUne fenêtre au-dessus de la page pour les formulaires et les tâches ciblées, avec en-tête et pied de page épinglés, imbrication, et une bottom sheet balayable sur mobile.
- DrawerUn panneau qui glisse depuis n’importe quel bord et suit votre doigt, avec des points d’accroche, une poignée fonctionnelle et des drawers imbriqués qui s’empilent.
- Dropdown menuUn menu d’actions et d’options derrière un bouton, avec groupes, sous-menus, éléments case à cocher et radio, et raccourcis.
- Hover cardUne carte d’aperçu qui s’ouvre au survol ou au focus d’un lien, pour un contenu que les personnes voyantes peuvent parcourir du regard.
Utilisé dans les blocks
Des blocks qui s’appuient sur Context menu.