HextaUI

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.

Right click here

Last action: Nothing yet

"use client"

import * as React from "react"

import {
  ContextMenu,
  ContextMenuCheckboxItem,
  ContextMenuContent,
  ContextMenuItem,
  ContextMenuLabel,
  ContextMenuRadioGroup,
  ContextMenuRadioItem,
  ContextMenuSeparator,
  ContextMenuShortcut,
  ContextMenuSub,
  ContextMenuSubContent,
  ContextMenuSubTrigger,
  ContextMenuTrigger,
} from "@/components/ui/context-menu"

export function ContextMenuDemo() {
  const [bookmarks, setBookmarks] = React.useState(true)
  const [urls, setUrls] = React.useState(false)
  const [person, setPerson] = React.useState("pedro")
  const [last, setLast] = React.useState("Nothing yet")

  return (
    <div className="flex w-full max-w-sm flex-col gap-2">
      <ContextMenu>
        <ContextMenuTrigger className="flex h-40 w-full items-center justify-center rounded-xl border border-dashed text-sm text-muted-foreground">
          Right click here
        </ContextMenuTrigger>
        <ContextMenuContent>
          <ContextMenuItem inset onClick={() => setLast("Back")}>
            Back
            <ContextMenuShortcut>⌘[</ContextMenuShortcut>
          </ContextMenuItem>
          <ContextMenuItem inset disabled>
            Forward
            <ContextMenuShortcut>⌘]</ContextMenuShortcut>
          </ContextMenuItem>
          <ContextMenuItem inset onClick={() => setLast("Reload")}>
            Reload
            <ContextMenuShortcut>⌘R</ContextMenuShortcut>
          </ContextMenuItem>
          <ContextMenuSub>
            <ContextMenuSubTrigger inset>More tools</ContextMenuSubTrigger>
            <ContextMenuSubContent>
              <ContextMenuItem onClick={() => setLast("Save page")}>
                Save page as…
                <ContextMenuShortcut>⇧⌘S</ContextMenuShortcut>
              </ContextMenuItem>
              <ContextMenuItem onClick={() => setLast("Create shortcut")}>
                Create shortcut…
              </ContextMenuItem>
              <ContextMenuItem onClick={() => setLast("Name window")}>
                Name window…
              </ContextMenuItem>
              <ContextMenuSeparator />
              <ContextMenuItem onClick={() => setLast("Developer tools")}>
                Developer tools
              </ContextMenuItem>
            </ContextMenuSubContent>
          </ContextMenuSub>
          <ContextMenuSeparator />
          <ContextMenuCheckboxItem
            checked={bookmarks}
            onCheckedChange={setBookmarks}
          >
            Show bookmarks bar
            <ContextMenuShortcut>⇧⌘B</ContextMenuShortcut>
          </ContextMenuCheckboxItem>
          <ContextMenuCheckboxItem checked={urls} onCheckedChange={setUrls}>
            Show full URLs
          </ContextMenuCheckboxItem>
          <ContextMenuSeparator />
          <ContextMenuRadioGroup value={person} onValueChange={setPerson}>
            <ContextMenuLabel inset>People</ContextMenuLabel>
            <ContextMenuRadioItem value="pedro">
              Pedro Duarte
            </ContextMenuRadioItem>
            <ContextMenuRadioItem value="colm">Colm Tuite</ContextMenuRadioItem>
          </ContextMenuRadioGroup>
        </ContextMenuContent>
      </ContextMenu>
      <p className="text-sm text-muted-foreground">Last action: {last}</p>
    </div>
  )
}
pnpm dlx shadcn@latest add https://hextaui.com/r/context-menu.json

Ajoute le composant, les tokens de thème HextaUI et les composants HextaUI dont il dépend.

import {
  ContextMenu,
  ContextMenuContent,
  ContextMenuItem,
  ContextMenuTrigger,
} from "@/components/ui/context-menu"
<ContextMenu>
  <ContextMenuTrigger>Right click here</ContextMenuTrigger>
  <ContextMenuContent>
    <ContextMenuItem>Profile</ContextMenuItem>
    <ContextMenuItem>Billing</ContextMenuItem>
    <ContextMenuItem variant="destructive">Delete</ContextMenuItem>
  </ContextMenuContent>
</ContextMenu>
ContextMenu
├── ContextMenuTrigger
└── ContextMenuContent
    ├── ContextMenuGroup
    │   ├── ContextMenuLabel
    │   └── ContextMenuItem
    │       └── ContextMenuShortcut
    ├── ContextMenuCheckboxItem
    ├── ContextMenuRadioGroup
    │   └── ContextMenuRadioItem
    ├── ContextMenuSeparator
    └── ContextMenuSub
        ├── ContextMenuSubTrigger
        └── ContextMenuSubContent

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.

"use client"

import * as React from "react"
import {
  IconCopy,
  IconDownload,
  IconFile,
  IconFolder,
  IconLink,
  IconMail,
  IconPencil,
  IconRefresh,
  IconShare,
  IconStar,
  IconTrash,
} from "@tabler/icons-react"

import {
  AlertDialog,
  AlertDialogAction,
  AlertDialogCancel,
  AlertDialogContent,
  AlertDialogDescription,
  AlertDialogFooter,
  AlertDialogHeader,
  AlertDialogTitle,
} from "@/components/ui/alert-dialog"
import { Button } from "@/components/ui/button"
import {
  ContextMenu,
  ContextMenuCheckboxItem,
  ContextMenuContent,
  ContextMenuItem,
  ContextMenuSeparator,
  ContextMenuShortcut,
  ContextMenuSub,
  ContextMenuSubContent,
  ContextMenuSubTrigger,
  ContextMenuTrigger,
} from "@/components/ui/context-menu"

const files = [
  { name: "Quarterly report.pdf", kind: "file" },
  { name: "Brand assets", kind: "folder" },
  { name: "Roadmap 2027.md", kind: "file" },
] as const

function FileRow({
  name,
  kind,
  onDelete,
}: {
  name: string
  kind: "file" | "folder"
  onDelete: () => void
}) {
  const [starred, setStarred] = React.useState(false)
  const Icon = kind === "folder" ? IconFolder : IconFile

  return (
    <ContextMenu>
      <ContextMenuTrigger className="flex items-center gap-3 rounded-lg px-3 py-2 text-sm hover:bg-muted/50 data-popup-open:bg-muted">
        <Icon className="size-4 text-muted-foreground" aria-hidden />
        <span className="min-w-0 flex-1 truncate">{name}</span>
        {starred ? (
          <IconStar
            className="size-4 text-muted-foreground"
            aria-label="Starred"
          />
        ) : null}
      </ContextMenuTrigger>
      <ContextMenuContent>
        <ContextMenuItem>
          <IconPencil />
          Rename…
        </ContextMenuItem>
        <ContextMenuItem>
          <IconCopy />
          Duplicate
          <ContextMenuShortcut>⌘D</ContextMenuShortcut>
        </ContextMenuItem>
        <ContextMenuItem>
          <IconDownload />
          Download
        </ContextMenuItem>
        <ContextMenuCheckboxItem checked={starred} onCheckedChange={setStarred}>
          Starred
        </ContextMenuCheckboxItem>
        <ContextMenuSub>
          <ContextMenuSubTrigger>
            <IconShare />
            Share
          </ContextMenuSubTrigger>
          <ContextMenuSubContent>
            <ContextMenuItem>
              <IconMail />
              Email
            </ContextMenuItem>
            <ContextMenuItem>
              <IconLink />
              Copy link
            </ContextMenuItem>
          </ContextMenuSubContent>
        </ContextMenuSub>
        <ContextMenuSeparator />
        <ContextMenuItem variant="destructive" onClick={onDelete}>
          <IconTrash />
          Delete
          <ContextMenuShortcut>⌘⌫</ContextMenuShortcut>
        </ContextMenuItem>
      </ContextMenuContent>
    </ContextMenu>
  )
}

export function ContextMenuFileList() {
  const [pending, setPending] = React.useState<string | null>(null)
  const [removed, setRemoved] = React.useState<string[]>([])

  return (
    <div className="flex w-full max-w-sm flex-col gap-3">
      <div className="flex flex-col gap-0.5 rounded-xl border p-1">
        {files
          .filter((file) => !removed.includes(file.name))
          .map((file) => (
            <FileRow
              key={file.name}
              name={file.name}
              kind={file.kind}
              onDelete={() => setPending(file.name)}
            />
          ))}
      </div>
      <div>
        <Button variant="outline" size="sm" onClick={() => setRemoved([])}>
          <IconRefresh />
          Restore files
        </Button>
      </div>
      <AlertDialog
        open={pending !== null}
        onOpenChange={(open) => {
          if (!open) {
            setPending(null)
          }
        }}
      >
        <AlertDialogContent size="sm">
          <AlertDialogHeader>
            <AlertDialogTitle>Delete “{pending}”?</AlertDialogTitle>
            <AlertDialogDescription>
              It moves to the trash for 30 days.
            </AlertDialogDescription>
          </AlertDialogHeader>
          <AlertDialogFooter>
            <AlertDialogCancel>Cancel</AlertDialogCancel>
            <AlertDialogAction
              variant="destructive"
              onClick={() => {
                if (pending) {
                  setRemoved((value) => [...value, pending])
                }
                setPending(null)
              }}
            >
              Delete
            </AlertDialogAction>
          </AlertDialogFooter>
        </AlertDialogContent>
      </AlertDialog>
    </div>
  )
}

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.

"use client"

import * as React from "react"
import { IconCopy, IconScissors } from "@tabler/icons-react"

import {
  ContextMenu,
  ContextMenuContent,
  ContextMenuItem,
  ContextMenuTrigger,
} from "@/components/ui/context-menu"

export function ContextMenuControlled() {
  const [open, setOpen] = React.useState(false)
  const [reason, setReason] = React.useState("—")

  return (
    <div className="flex w-full max-w-sm flex-col gap-2">
      <ContextMenu
        open={open}
        onOpenChange={(next, details) => {
          setOpen(next)
          setReason(details.reason)
        }}
      >
        <ContextMenuTrigger className="flex h-40 w-full items-center justify-center rounded-xl border border-dashed text-sm text-muted-foreground">
          Controlled area
        </ContextMenuTrigger>
        <ContextMenuContent>
          <ContextMenuItem>
            <IconScissors />
            Cut
          </ContextMenuItem>
          <ContextMenuItem>
            <IconCopy />
            Copy
          </ContextMenuItem>
          <ContextMenuItem closeOnClick={false}>
            Stays open on click
          </ContextMenuItem>
        </ContextMenuContent>
      </ContextMenu>
      <p className="text-sm text-muted-foreground">
        Open: {String(open)} · last reason: {reason}
      </p>
    </div>
  )
}

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.

import { IconTrash } from "@tabler/icons-react"

import {
  ContextMenu,
  ContextMenuContent,
  ContextMenuItem,
  ContextMenuTrigger,
} from "@/components/ui/context-menu"

export function ContextMenuDisabled() {
  return (
    <div className="grid w-full max-w-lg gap-3 sm:grid-cols-2">
      <ContextMenu disabled>
        <ContextMenuTrigger className="flex h-40 w-full items-center justify-center rounded-xl border border-dashed text-sm text-muted-foreground">
          Disabled menu
        </ContextMenuTrigger>
        <ContextMenuContent>
          <ContextMenuItem>Never shown</ContextMenuItem>
        </ContextMenuContent>
      </ContextMenu>
      <ContextMenu>
        <ContextMenuTrigger className="flex h-40 w-full items-center justify-center rounded-xl border border-dashed text-sm text-muted-foreground">
          Disabled items
        </ContextMenuTrigger>
        <ContextMenuContent>
          <ContextMenuItem>Enabled</ContextMenuItem>
          <ContextMenuItem disabled>Disabled item</ContextMenuItem>
          <ContextMenuItem variant="destructive" disabled>
            <IconTrash />
            Disabled destructive
          </ContextMenuItem>
        </ContextMenuContent>
      </ContextMenu>
    </div>
  )
}

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.

import {
  ContextMenu,
  ContextMenuContent,
  ContextMenuItem,
  ContextMenuTrigger,
} from "@/components/ui/context-menu"

export function ContextMenuHoldFeedback() {
  return (
    <div className="grid w-full max-w-lg gap-3 sm:grid-cols-2">
      <ContextMenu>
        <ContextMenuTrigger className="flex h-40 w-full items-center justify-center rounded-xl border border-dashed text-sm text-muted-foreground">
          Press and hold
        </ContextMenuTrigger>
        <ContextMenuContent>
          <ContextMenuItem>Copy</ContextMenuItem>
          <ContextMenuItem>Paste</ContextMenuItem>
        </ContextMenuContent>
      </ContextMenu>
      <ContextMenu>
        <ContextMenuTrigger
          holdFeedback={false}
          className="flex h-40 w-full items-center justify-center rounded-xl border border-dashed text-sm text-muted-foreground"
        >
          No hold feedback
        </ContextMenuTrigger>
        <ContextMenuContent>
          <ContextMenuItem>Copy</ContextMenuItem>
          <ContextMenuItem>Paste</ContextMenuItem>
        </ContextMenuContent>
      </ContextMenu>
    </div>
  )
}

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.

import { IconFile } from "@tabler/icons-react"

import {
  ContextMenu,
  ContextMenuContent,
  ContextMenuGroup,
  ContextMenuItem,
  ContextMenuLabel,
  ContextMenuShortcut,
  ContextMenuTrigger,
} from "@/components/ui/context-menu"

export function ContextMenuLongContent() {
  return (
    <div className="grid w-full max-w-lg gap-3 sm:grid-cols-2">
      <ContextMenu>
        <ContextMenuTrigger className="flex h-40 w-full items-center justify-center rounded-xl border border-dashed text-sm text-muted-foreground">
          Long labels
        </ContextMenuTrigger>
        <ContextMenuContent>
          <ContextMenuLabel>
            A label that goes on for much longer than any menu label should
          </ContextMenuLabel>
          <ContextMenuItem>
            <IconFile />
            Move to “Supercalifragilisticexpialidocious project archive 2026”
            <ContextMenuShortcut>⌥⌘M</ContextMenuShortcut>
          </ContextMenuItem>
          <ContextMenuItem>
            https://example.com/a/really/long/url/without/any/spaces/at/all/in/it
          </ContextMenuItem>
          <ContextMenuItem>مرحبا بالعالم — mixed العربية text</ContextMenuItem>
          <ContextMenuItem>👩‍👩‍👧‍👦 Family 日本語のテキスト</ContextMenuItem>
          <ContextMenuItem>Short</ContextMenuItem>
        </ContextMenuContent>
      </ContextMenu>
      <ContextMenu>
        <ContextMenuTrigger className="flex h-40 w-full items-center justify-center rounded-xl border border-dashed text-sm text-muted-foreground">
          40 items
        </ContextMenuTrigger>
        <ContextMenuContent>
          <ContextMenuGroup>
            <ContextMenuLabel>Recent</ContextMenuLabel>
            {Array.from({ length: 40 }, (_, index) => (
              <ContextMenuItem key={index}>
                Document {index + 1}
              </ContextMenuItem>
            ))}
          </ContextMenuGroup>
        </ContextMenuContent>
      </ContextMenu>
    </div>
  )
}

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.

import {
  ContextMenu,
  ContextMenuContent,
  ContextMenuItem,
  ContextMenuSub,
  ContextMenuSubContent,
  ContextMenuSubTrigger,
  ContextMenuTrigger,
} from "@/components/ui/context-menu"

export function ContextMenuNested() {
  return (
    <ContextMenu>
      <ContextMenuTrigger className="flex h-40 w-full max-w-sm items-center justify-center rounded-xl border border-dashed text-sm text-muted-foreground">
        Three levels deep
      </ContextMenuTrigger>
      <ContextMenuContent>
        <ContextMenuItem>Open</ContextMenuItem>
        <ContextMenuSub>
          <ContextMenuSubTrigger>Move to</ContextMenuSubTrigger>
          <ContextMenuSubContent>
            <ContextMenuItem>Inbox</ContextMenuItem>
            <ContextMenuSub>
              <ContextMenuSubTrigger>Projects</ContextMenuSubTrigger>
              <ContextMenuSubContent>
                <ContextMenuItem>Acme</ContextMenuItem>
                <ContextMenuSub>
                  <ContextMenuSubTrigger>Archive</ContextMenuSubTrigger>
                  <ContextMenuSubContent>
                    <ContextMenuItem>2024</ContextMenuItem>
                    <ContextMenuItem>2025</ContextMenuItem>
                  </ContextMenuSubContent>
                </ContextMenuSub>
              </ContextMenuSubContent>
            </ContextMenuSub>
            <ContextMenuSub disabled>
              <ContextMenuSubTrigger disabled>Locked</ContextMenuSubTrigger>
              <ContextMenuSubContent>
                <ContextMenuItem>Hidden</ContextMenuItem>
              </ContextMenuSubContent>
            </ContextMenuSub>
          </ContextMenuSubContent>
        </ContextMenuSub>
        <ContextMenuItem variant="destructive">Delete</ContextMenuItem>
      </ContextMenuContent>
    </ContextMenu>
  )
}

Dans une sheet

Le menu se superpose aux autres surcouches, et Escape ne ferme que le menu, pas la sheet derrière lui.

import { Button } from "@/components/ui/button"
import {
  ContextMenu,
  ContextMenuContent,
  ContextMenuItem,
  ContextMenuTrigger,
} from "@/components/ui/context-menu"
import {
  Sheet,
  SheetBody,
  SheetContent,
  SheetDescription,
  SheetHeader,
  SheetTitle,
  SheetTrigger,
} from "@/components/ui/sheet"

export function ContextMenuInSheet() {
  return (
    <Sheet>
      <SheetTrigger render={<Button variant="outline" />}>
        Open sheet
      </SheetTrigger>
      <SheetContent>
        <SheetHeader>
          <SheetTitle>Inside a sheet</SheetTitle>
          <SheetDescription>
            The menu layers above the sheet and Escape closes only the menu.
          </SheetDescription>
        </SheetHeader>
        <SheetBody>
          <ContextMenu>
            <ContextMenuTrigger className="flex h-40 w-full items-center justify-center rounded-xl border border-dashed text-sm text-muted-foreground">
              Right click here
            </ContextMenuTrigger>
            <ContextMenuContent>
              <ContextMenuItem>Copy</ContextMenuItem>
              <ContextMenuItem>Paste</ContextMenuItem>
            </ContextMenuContent>
          </ContextMenu>
        </SheetBody>
      </SheetContent>
    </Sheet>
  )
}

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.

import { IconDownload, IconLink } from "@tabler/icons-react"

import {
  ContextMenu,
  ContextMenuContent,
  ContextMenuItem,
  ContextMenuTrigger,
} from "@/components/ui/context-menu"

export function ContextMenuRender() {
  return (
    <ContextMenu>
      <ContextMenuTrigger
        render={<figure />}
        className="flex w-full max-w-xs flex-col gap-2 rounded-xl border p-3"
      >
        <div className="h-28 rounded-lg bg-muted" />
        <figcaption className="text-sm text-muted-foreground">
          Trigger rendered as a figure
        </figcaption>
      </ContextMenuTrigger>
      <ContextMenuContent>
        <ContextMenuItem>
          <IconDownload />
          Save image
        </ContextMenuItem>
        <ContextMenuItem render={<a href="#render-as-another-element" />}>
          <IconLink />
          Link item
        </ContextMenuItem>
      </ContextMenuContent>
    </ContextMenu>
  )
}

De droite à gauche

Le menu lit la direction du déclencheur : les sous-menus s’ouvrent donc à gauche et les flèches s’inversent.

import { IconArrowLeft, IconArrowRight, IconTrash } from "@tabler/icons-react"

import {
  ContextMenu,
  ContextMenuCheckboxItem,
  ContextMenuContent,
  ContextMenuItem,
  ContextMenuSeparator,
  ContextMenuShortcut,
  ContextMenuSub,
  ContextMenuSubContent,
  ContextMenuSubTrigger,
  ContextMenuTrigger,
} from "@/components/ui/context-menu"

export function ContextMenuRtl() {
  return (
    <div dir="rtl" className="w-full max-w-sm">
      <ContextMenu>
        <ContextMenuTrigger className="flex h-40 w-full items-center justify-center rounded-xl border border-dashed text-sm text-muted-foreground">
          انقر بزر الفأرة الأيمن هنا
        </ContextMenuTrigger>
        <ContextMenuContent>
          <ContextMenuItem>
            <IconArrowRight />
            رجوع
            <ContextMenuShortcut>⌘[</ContextMenuShortcut>
          </ContextMenuItem>
          <ContextMenuItem>
            <IconArrowLeft />
            تقدم
          </ContextMenuItem>
          <ContextMenuCheckboxItem defaultChecked>
            إظهار الشريط
          </ContextMenuCheckboxItem>
          <ContextMenuSub>
            <ContextMenuSubTrigger>مشاركة</ContextMenuSubTrigger>
            <ContextMenuSubContent>
              <ContextMenuItem>بريد</ContextMenuItem>
              <ContextMenuItem>نسخ الرابط</ContextMenuItem>
            </ContextMenuSubContent>
          </ContextMenuSub>
          <ContextMenuSeparator />
          <ContextMenuItem variant="destructive">
            <IconTrash />
            حذف
          </ContextMenuItem>
        </ContextMenuContent>
      </ContextMenu>
    </div>
  )
}
ToucheAction
↓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.
HomeMet en évidence le premier élément.
EndMet en évidence le dernier élément.
EnterSpaceExé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.
EscFerme le menu actuel. Dans un sous-menu, seul ce sous-menu se ferme.
A–ZMet 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.

PropTypePar défaut
open
boolean–
defaultOpen
booleanfalse
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.
booleanfalse
loopFocusReboucle la navigation aux flèches aux extrémités.
booleantrue
highlightItemOnHover
booleantrue
actionsRefFerme le menu de façon impérative.
RefObject<{ close, unmount }>–
PropTypePar défaut
holdFeedbackRéduit légèrement la zone pendant un appui long sur écran tactile.
booleantrue
render
ReactElement | (props, state) => ReactElement<div>
AttributDescription
data-slot="context-menu-trigger"Ciblez le déclencheur en CSS.
data-popup-openPrésent tant que son menu est ouvert.
data-holdingPrésent pendant un appui long.
data-pressedPrésent tant que le déclencheur est enfoncé.
PropTypePar 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
number0
alignOffset
number0
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>
AttributDescription
data-slot="context-menu-content"La popup du menu.
data-openPrésent tant que l’élément est ouvert.
data-starting-stylePrésent pendant l’animation d’entrée du menu.
data-ending-stylePrésent pendant l’animation de sortie du menu.
data-sideLe côté sur lequel il a été placé après les collisions.
data-chosenPrésent après le clic sur un élément. Le fondu de sortie attend le clignotement.
--transform-originLe point d’où part l’animation d’agrandissement.
--available-heightEspace restant dans le viewport. Plafonne la hauteur du menu.
PropTypePar défaut
variant
"default" | "destructive""default"
insetDécale le libellé pour l’aligner avec les éléments à case à cocher.
booleanfalse
onClickS’exécute au clic, sur Enter ou Space. Le menu se ferme après un court clignotement.
(event) => void–
closeOnClick
booleantrue
disabled
booleanfalse
labelTexte utilisé pour la recherche à la frappe lorsque les enfants ne sont pas du texte simple.
string–
render
ReactElement | (props, state) => ReactElement<div>
AttributDescription
data-slot="context-menu-item"Ciblez les items en CSS.
data-variantLa variante actuelle.
data-highlightedPrésent sur l’élément sous le pointeur ou ayant le focus clavier.
data-disabledPrésent lorsque l’item est désactivé.
data-insetPrésent lorsque inset est défini.
data-chosenPrésent sur l’élément cliqué pendant son clignotement.
PropTypePar défaut
checked
boolean–
defaultChecked
booleanfalse
onCheckedChange
(checked: boolean, details) => void–
closeOnClick
booleanfalse
inset
booleanfalse
disabled
booleanfalse
render
ReactElement | (props, state) => ReactElement<div>
AttributDescription
data-slot="context-menu-checkbox-item"Ciblez les éléments à case à cocher en CSS.
data-checkedPrésent lorsqu’il est coché.
data-uncheckedPrésent lorsqu’il est décoché.
data-highlightedPrésent sur l’élément sous le pointeur ou ayant le focus clavier.
data-disabledPrésent lorsque l’item est désactivé.
data-insetPrésent lorsque inset est défini.
data-chosenPrésent sur l’élément cliqué pendant son clignotement.
PropTypePar défaut
value
any–
defaultValue
any–
onValueChange
(value: any, details) => void–
disabled
booleanfalse
PropTypePar défaut
value
any–
closeOnClick
booleanfalse
inset
booleanfalse
disabled
booleanfalse
render
ReactElement | (props, state) => ReactElement<div>
AttributDescription
data-slot="context-menu-radio-item"Ciblez les éléments radio en CSS.
data-checkedPrésent lorsqu’il est sélectionné.
data-highlightedPrésent sur l’élément sous le pointeur ou ayant le focus clavier.
data-disabledPrésent lorsque l’item est désactivé.
data-insetPrésent lorsque inset est défini.
data-chosenPrésent sur l’élément cliqué pendant son clignotement.
PropTypePar défaut
inset
booleanfalse
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.

PropTypePar défaut
open
boolean–
defaultOpen
booleanfalse
onOpenChange
(open: boolean, details) => void–
disabled
booleanfalse
closeParentOnEscFerme tout le menu avec Escape, et pas seulement ce sous-menu.
booleanfalse
PropTypePar défaut
inset
booleanfalse
openOnHover
booleantrue
delayMillisecondes de survol avant l’ouverture du sous-menu.
number100
closeDelay
number0
disabled
booleanfalse
render
ReactElement | (props, state) => ReactElement<div>
AttributDescription
data-slot="context-menu-sub-trigger"Ciblez les déclencheurs de sous-menu en CSS.
data-popup-openPrésent tant que son sous-menu est ouvert.
data-highlightedPrésent pendant la mise en surbrillance.
data-disabledPrésent lorsque l’élément est désactivé.
PropTypePar 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
number0
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>
AttributDescription
data-slot="context-menu-sub-content"La popup du sous-menu. Prend les mêmes attributs d’état que le menu.
PropTypePar défaut
dirGarde les raccourcis comme ⇧⌘S dans l’ordre dans les menus de droite à gauche.
"ltr" | "rtl""ltr"
AttributDescription
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.

Utilisé dans les blocks

Des blocks qui s’appuient sur Context menu.