HextaUI

Context menu

Um menu de ações ao clicar com o botão direito ou pressionar e segurar, com submenus, itens de checkbox e de rádio e feedback de pressão no toque.

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

Adiciona o componente, os tokens de tema do HextaUI e quaisquer componentes do HextaUI dos quais ele depende.

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

Lista de arquivos

Dê a cada linha o seu próprio menu. A linha aberta mantém um destaque, e um item destrutivo passa a um alert dialog para confirmação.

"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>
  )
}

Controlado

Passe open e onOpenChange para controlar o estado. O segundo argumento diz por que mudou, como trigger-press, outside-press ou escape-key. Itens com closeOnClick={false} o mantêm aberto.

"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>
  )
}

Desabilitado

Um <ContextMenu /> desativado devolve a área ao menu nativo do navegador. Itens desativados continuam visíveis, mas são ignorados pelo teclado.

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>
  )
}

Feedback de pressão longa

Em telas sensíveis ao toque, o menu abre após um toque longo. Enquanto o dedo é mantido, a área encolhe um pouco para que as pessoas saibam que o toque foi registrado. Mover o dedo o cancela. Defina holdFeedback={false} para desativar.

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>
  )
}

Conteúdo longo

Rótulos longos quebram de linha dentro de uma largura máxima de 20rem, e menus altos rolam dentro do espaço restante no 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>
  )
}

Submenus aninhados

Os submenus abrem ao passar o mouse ou com as teclas de seta, em qualquer profundidade. Um gatilho de submenu desativado nunca abre.

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>
  )
}

Dentro de uma sheet

O menu fica acima de outras sobreposições, e Escape fecha apenas o menu, não o sheet atrás dele.

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>
  )
}

Renderizar como outro elemento

Use render para fazer do gatilho qualquer elemento, como um figure, ou para transformar um item em link.

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>
  )
}

Da direita para a esquerda

O menu lê a direção do gatilho, então os submenus abrem para a esquerda e as teclas de seta se invertem.

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>
  )
}
TeclaAção
↓Destaca o próximo item, voltando ao início no fim.
↑Destaca o item anterior, voltando ao fim no início.
HomeDestaca o primeiro item.
EndDestaca o último item.
EnterSpaceExecuta o item destacado. Itens de checkbox e radio alternam e mantêm o menu aberto.
→Abre o submenu destacado e entra nele. ← em layouts da direita para a esquerda.
←Fecha o submenu atual e volta ao seu gatilho. → em layouts da direita para a esquerda.
EscFecha o menu atual. Em um submenu, apenas esse submenu fecha.
A–ZDestaca o próximo item que começa com aquela letra.
  • Um context menu é um atalho. Torne toda ação nele acessível de outra forma também, como um botão visível ou um dropdown menu, já que muitas pessoas nunca usam o clique direito nem o toque longo.
  • Os navegadores também disparam o evento de context menu para Shift F10 e a tecla Menu em um elemento focado, então um elemento focável dentro do gatilho permite que usuários de teclado o abram.
  • Os atalhos em <ContextMenuShortcut /> são apenas rótulos. Associe as teclas você mesmo.
  • Com movimento reduzido ativado, o feedback de pressão longa e o piscar do item são ignorados e o menu apenas faz fade.

Construído sobre o context menu do Base UI. Cada parte aceita as props da primitiva que envolve, e um className em forma de função que recebe o estado da parte.

PropTipoPadrão
open
boolean–
defaultOpen
booleanfalse
onOpenChangedetails.reason informa o que causou a mudança.
(open: boolean, details) => void–
onOpenChangeCompleteExecuta depois que a animação de abertura ou fechamento termina.
(open: boolean) => void–
disabledMostra o menu nativo do navegador.
booleanfalse
loopFocusVolta ao início nas pontas da navegação por teclas de seta.
booleantrue
highlightItemOnHover
booleantrue
actionsRefFecha o menu de forma imperativa.
RefObject<{ close, unmount }>–
PropTipoPadrão
holdFeedbackEncolhe um pouco a área enquanto um toque longo é mantido em telas sensíveis ao toque.
booleantrue
render
ReactElement | (props, state) => ReactElement<div>
AtributoDescrição
data-slot="context-menu-trigger"Selecione o gatilho no CSS.
data-popup-openPresente enquanto o menu está aberto.
data-holdingPresente enquanto um toque longo é mantido.
data-pressedPresente enquanto o gatilho está pressionado.
PropTipoPadrão
sideLado preferido, em relação ao ponteiro.
"top" | "right" | "bottom" | "left" | "inline-start" | "inline-end""bottom"
align
"start" | "center" | "end""start"
sideOffset
number0
alignOffset
number0
collisionPaddingEspaço a manter entre o menu e as bordas do viewport.
number | { top, right, bottom, left }–
collisionAvoidanceComo o menu se inverte ou se desloca quando transbordaria.
CollisionAvoidance–
anchorPosiciona em relação a algo diferente do ponteiro.
Element | VirtualElement | RefObject–
finalFocusPara onde o foco vai depois que o menu fecha.
boolean | RefObject | (closeType) => HTMLElement | boolean–
render
ReactElement | (props, state) => ReactElement<div>
AtributoDescrição
data-slot="context-menu-content"O popup do menu.
data-openPresente enquanto aberto.
data-starting-stylePresente enquanto o menu anima a entrada.
data-ending-stylePresente enquanto o menu anima a saída.
data-sideO lado em que foi posicionado após as colisões.
data-chosenPresente depois que um item é clicado. O fade-out espera o piscar.
--transform-originO ponto de onde a animação de escala cresce.
--available-heightEspaço restante no viewport. Limita a altura do menu.
PropTipoPadrão
variant
"default" | "destructive""default"
insetRecua o rótulo para alinhá-lo aos itens com checkbox.
booleanfalse
onClickExecuta ao clicar, com Enter ou Space. O menu fecha após um breve piscar.
(event) => void–
closeOnClick
booleantrue
disabled
booleanfalse
labelTexto usado na busca por digitação quando os children não são texto simples.
string–
render
ReactElement | (props, state) => ReactElement<div>
AtributoDescrição
data-slot="context-menu-item"Selecione itens no CSS.
data-variantA variante atual.
data-highlightedPresente no item sob o ponteiro ou com foco do teclado.
data-disabledPresente quando o item está desabilitado.
data-insetPresente quando inset está definido.
data-chosenPresente no item clicado enquanto ele pisca.
PropTipoPadrão
checked
boolean–
defaultChecked
booleanfalse
onCheckedChange
(checked: boolean, details) => void–
closeOnClick
booleanfalse
inset
booleanfalse
disabled
booleanfalse
render
ReactElement | (props, state) => ReactElement<div>
AtributoDescrição
data-slot="context-menu-checkbox-item"Seleciona os itens com checkbox no CSS.
data-checkedPresente quando marcado.
data-uncheckedPresente quando desmarcado.
data-highlightedPresente no item sob o ponteiro ou com foco do teclado.
data-disabledPresente quando o item está desabilitado.
data-insetPresente quando inset está definido.
data-chosenPresente no item clicado enquanto ele pisca.
PropTipoPadrão
value
any–
defaultValue
any–
onValueChange
(value: any, details) => void–
disabled
booleanfalse
PropTipoPadrão
value
any–
closeOnClick
booleanfalse
inset
booleanfalse
disabled
booleanfalse
render
ReactElement | (props, state) => ReactElement<div>
AtributoDescrição
data-slot="context-menu-radio-item"Seleciona os itens radio no CSS.
data-checkedPresente quando selecionado.
data-highlightedPresente no item sob o ponteiro ou com foco do teclado.
data-disabledPresente quando o item está desabilitado.
data-insetPresente quando inset está definido.
data-chosenPresente no item clicado enquanto ele pisca.
PropTipoPadrão
inset
booleanfalse
render
ReactElement | (props, state) => ReactElement<div>

Dentro de <ContextMenuGroup /> ou <ContextMenuRadioGroup />, rotula o grupo para tecnologias assistivas. Em outros lugares, é um heading simples.

PropTipoPadrão
open
boolean–
defaultOpen
booleanfalse
onOpenChange
(open: boolean, details) => void–
disabled
booleanfalse
closeParentOnEscFecha o menu inteiro com Escape, não apenas este submenu.
booleanfalse
PropTipoPadrão
inset
booleanfalse
openOnHover
booleantrue
delayMilissegundos de hover antes de o submenu abrir.
number100
closeDelay
number0
disabled
booleanfalse
render
ReactElement | (props, state) => ReactElement<div>
AtributoDescrição
data-slot="context-menu-sub-trigger"Seleciona os gatilhos de submenu no CSS.
data-popup-openPresente enquanto o seu submenu está aberto.
data-highlightedPresente enquanto destacado.
data-disabledPresente quando desabilitado.
PropTipoPadrão
sideAbre em direção ao fim da linha por padrão.
"top" | "right" | "bottom" | "left" | "inline-start" | "inline-end"–
align
"start" | "center" | "end"–
sideOffset
number0
alignOffset
number-4
collisionPaddingEspaço a manter entre o menu e as bordas do viewport.
number | { top, right, bottom, left }–
collisionAvoidanceComo o menu se inverte ou se desloca quando transbordaria.
CollisionAvoidance–
anchorPosiciona em relação a algo diferente do ponteiro.
Element | VirtualElement | RefObject–
render
ReactElement | (props, state) => ReactElement<div>
AtributoDescrição
data-slot="context-menu-sub-content"O popup do submenu. Recebe os mesmos atributos de estado do menu.
PropTipoPadrão
dirMantém atalhos como ⇧⌘S em ordem dentro de menus da direita para a esquerda.
"ltr" | "rtl""ltr"
AtributoDescrição
data-slot="context-menu-shortcut"O rótulo do atalho.

<ContextMenuGroup /> agrupa itens relacionados sob um rótulo. <ContextMenuSeparator /> desenha um divisor. Ambos aceitam render e className, e carregam context-menu-group e context-menu-separator como seu data-slot.

Usado em blocos

Blocos que se baseiam em Context menu.