Install the component from your command line.
npm install @radix-ui/react-context-menu
Copy Import the components and piece the parts together.
import * as ContextMenu from '@radix-ui/react-context-menu' ;
export default ( ) => (
< ContextMenu.Root >
< ContextMenu.Trigger />
< ContextMenu.Content >
< ContextMenu.Label />
< ContextMenu.Item />
< ContextMenu.Group >
< ContextMenu.Item />
</ ContextMenu.Group >
< ContextMenu.CheckboxItem >
< ContextMenu.ItemIndicator />
</ ContextMenu.CheckboxItem >
< ContextMenu.RadioGroup >
< ContextMenu.RadioItem >
< ContextMenu.ItemIndicator />
</ ContextMenu.RadioItem >
</ ContextMenu.RadioGroup >
< ContextMenu.Separator />
</ ContextMenu.Content >
</ ContextMenu.Root >
) ;
Copy Create your styled context menu component from the primitive parts.
import * as ContextMenu from '@radix-ui/react-context-menu' ;
const StyledContent = styled ( ContextMenu . Content , {
minWidth : 130 ,
backgroundColor : 'white' ,
borderRadius : 6 ,
padding : 5 ,
boxShadow : '0px 5px 15px -5px hsla(206,22%,7%,.15)' ,
} ) ;
const StyledItem = styled ( ContextMenu . Item , {
fontSize : 13 ,
padding : '5px 10px' ,
borderRadius : 3 ,
cursor : 'default' ,
'&:focus' : {
outline : 'none' ,
backgroundColor : 'dodgerblue' ,
color : 'white' ,
} ,
} ) ;
export default ( ) => (
< ContextMenu.Root >
< ContextMenu.Trigger >
< div
style = { {
backgroundColor : 'gainsboro' ,
padding : 50 ,
textAlign : 'center' ,
} }
>
Right click anywhere
</ div >
</ ContextMenu.Trigger >
< StyledContent >
< StyledItem > Cut </ StyledItem >
< StyledItem > Copy </ StyledItem >
< StyledItem > Paste </ StyledItem >
</ StyledContent >
</ ContextMenu.Root >
) ;
Copy Adheres to the Menu WAI-ARIA design pattern and uses roving tabindex to manage focus movement among menu items.
Contains all the parts of a context menu.
The area that opens the context menu. Wrap it around the target you want the context menu to open from when right-clicking (or using the relevant keyboard shortcuts).
Prop Type Default Required as
enum
span
The component that pops out in an open context menu.
Prop Type Default Required as
enum
div
disableOutsidePointerEvents
boolean
true
onEscapeKeyDown
function
onPointerDownOutside
function
onInteractOutside
function
forceMount
boolean
side
enum
"bottom"
sideOffset
number
0
align
enum
"center"
alignOffset
number
0
avoidCollisions
boolean
true
collisionTolerance
boolean
0
The component that contains the context menu items.
Prop Type Default Required as
enum
div
disabled
boolean
onSelect
function
textValue
string
Used to group multiple ContextMenu.Item
s.
Prop Type Default Required as
enum
div
Used to render a label. It won't be focusable using arrow keys.
Prop Type Default Required as
enum
div
An item that can be controlled and rendered like a checkbox.
Prop Type Default Required as
enum
div
checked
boolean
onCheckedChange
function
disabled
boolean
onSelect
function
textValue
string
Used to group multiple ContextMenu.RadioItem
s.
Prop Type Default Required as
enum
div
value
string
onValueChange
function
An item that can be controlled and rendered like a radio.
Prop Type Default Required as
enum
div
value
string
disabled
boolean
onSelect
function
textValue
string
Renders when the parent ContextMenu.CheckboxItem
or ContextMenu.RadioItem
is checked. You can style this element directly, or you can use it as a wrapper to put an icon into, or both.
Prop Type Default Required as
enum
span
forceMount
boolean
Used to visually separate items in the context menu.
Prop Type Default Required as
enum
div
We expose a CSS custom property --radix-context-menu-content-transform-origin
. Use it to animate the content from its computed origin based on side
, sideOffset
, align
, alignOffset
and any collisions.
const scaleIn = css . keyframes ( {
'0%' : { opacity : 0 , transform : 'scale(0)' } ,
'100%' : { opacity : 1 , transform : 'scale(1)' } ,
} ) ;
const StyledContent = styled ( ContextMenu . Content , {
transformOrigin :
'var(--radix-context-menu-content-transform-origin)' ,
animation : ` ${ scaleIn } 0.5s ease-out ` ,
} ) ;
Copy We expose data-side
and data-align
attributes. Their values will change at runtime to reflect collisions. Use them to create collision and direction-aware animations.
const slideDown = css . keyframes ( {
'0%' : { opacity : 0 , transform : 'translateY(-10px)' } ,
'100%' : { opacity : 1 , transform : 'translateY(0)' } ,
} ) ;
const slideUp = css . keyframes ( {
'0%' : { opacity : 0 , transform : 'translateY(10px)' } ,
'100%' : { opacity : 1 , transform : 'translateY(0)' } ,
} ) ;
const StyledContent = styled ( ContextMenu . Content , {
'&[data-side="top"]' : { animationName : slideUp } ,
'&[data-side="bottom"]' : { animationName : slideDown } ,
animationDuration : '0.6s' ,
animationTimingFunction : 'cubic-bezier(0.16, 1, 0.3, 1)' ,
} ) ;
Copy You can add special styles to disabled items via the data-disabled
attribute.
Show code
import * as ContextMenu from '@radix-ui/react-context-menu' ;
const StyledContent = styled ( ContextMenu . Content , {
minWidth : 130 ,
backgroundColor : 'white' ,
borderRadius : 6 ,
padding : 5 ,
boxShadow : '0px 5px 15px -5px hsla(206,22%,7%,.15)' ,
} ) ;
const StyledItem = styled ( ContextMenu . Item , {
fontSize : 13 ,
padding : '5px 10px' ,
borderRadius : 3 ,
cursor : 'default' ,
'&[data-disabled]' : {
color : 'gainsboro' ,
} ,
'&:focus' : {
outline : 'none' ,
backgroundColor : 'dodgerblue' ,
color : 'white' ,
} ,
} ) ;
export default ( ) => (
< ContextMenu.Root >
< ContextMenu.Trigger >
< div
style = { {
backgroundColor : 'gainsboro' ,
padding : 50 ,
textAlign : 'center' ,
} }
>
Right click anywhere
</ div >
</ ContextMenu.Trigger >
< StyledContent >
< StyledItem disabled > Cut </ StyledItem >
< StyledItem > Copy </ StyledItem >
< StyledItem > Paste </ StyledItem >
</ StyledContent >
</ ContextMenu.Root >
) ;
Copy Use the Separator
part to add a separator between items.
Show code
import * as ContextMenu from '@radix-ui/react-context-menu' ;
const StyledContent = styled ( ContextMenu . Content , {
minWidth : 130 ,
backgroundColor : 'white' ,
borderRadius : 6 ,
padding : 5 ,
boxShadow : '0px 5px 15px -5px hsla(206,22%,7%,.15)' ,
} ) ;
const StyledItem = styled ( ContextMenu . Item , {
fontSize : 13 ,
padding : '5px 10px' ,
borderRadius : 3 ,
cursor : 'default' ,
'&:focus' : {
outline : 'none' ,
backgroundColor : 'dodgerblue' ,
color : 'white' ,
} ,
} ) ;
const StyledSeparator = styled ( ContextMenu . Separator , {
height : 1 ,
backgroundColor : 'gainsboro' ,
margin : 5 ,
} ) ;
export default ( ) => (
< ContextMenu.Root >
< ContextMenu.Trigger >
< div
style = { {
backgroundColor : 'gainsboro' ,
padding : 50 ,
textAlign : 'center' ,
} }
>
Right click anywhere
</ div >
</ ContextMenu.Trigger >
< StyledContent >
< StyledItem > Undo </ StyledItem >
< StyledItem > Redo </ StyledItem >
< StyledSeparator />
< StyledItem > Cut </ StyledItem >
< StyledItem > Copy </ StyledItem >
< StyledItem > Paste </ StyledItem >
</ StyledContent >
</ ContextMenu.Root >
) ;
Copy Use the Label
part to help label a section.
Show code
import * as ContextMenu from '@radix-ui/react-context-menu' ;
const StyledContent = styled ( ContextMenu . Content , {
minWidth : 130 ,
backgroundColor : 'white' ,
borderRadius : 6 ,
padding : 5 ,
boxShadow : '0px 5px 15px -5px hsla(206,22%,7%,.15)' ,
} ) ;
const StyledItem = styled ( ContextMenu . Item , {
fontSize : 13 ,
padding : '5px 10px' ,
borderRadius : 3 ,
cursor : 'default' ,
'&:focus' : {
outline : 'none' ,
backgroundColor : 'dodgerblue' ,
color : 'white' ,
} ,
} ) ;
const StyledLabel = styled ( ContextMenu . Label , {
color : 'slategray' ,
fontSize : 13 ,
padding : '5px 10px' ,
cursor : 'default' ,
} ) ;
const StyledSeparator = styled ( ContextMenu . Separator , {
height : 1 ,
backgroundColor : 'gainsboro' ,
margin : 5 ,
} ) ;
export default ( ) => (
< ContextMenu.Root >
< ContextMenu.Trigger >
< div
style = { {
backgroundColor : 'gainsboro' ,
padding : 50 ,
textAlign : 'center' ,
} }
>
Right click anywhere
</ div >
</ ContextMenu.Trigger >
< StyledContent >
< StyledLabel > Recently Closed </ StyledLabel >
< StyledItem > Modulz </ StyledItem >
< StyledItem > Radix - ui </ StyledItem >
< StyledItem > Stitches </ StyledItem >
< StyledSeparator />
< StyledLabel > Recently Visited </ StyledLabel >
< StyledItem > GitHub </ StyledItem >
< StyledItem > Modulz </ StyledItem >
</ StyledContent >
</ ContextMenu.Root >
) ;
Copy Use the CheckboxItem
part to add an item that can be checked.
Show code
import * as ContextMenu from '@radix-ui/react-context-menu' ;
import { CheckIcon } from '@modulz/radix-icons' ;
const StyledContent = styled ( ContextMenu . Content , {
minWidth : 130 ,
backgroundColor : 'white' ,
borderRadius : 6 ,
padding : 5 ,
boxShadow : '0px 5px 15px -5px hsla(206,22%,7%,.15)' ,
} ) ;
const itemStyles = {
fontSize : 13 ,
padding : '5px 10px 5px 25px' ,
borderRadius : 3 ,
cursor : 'default' ,
position : 'relative' ,
'&:focus' : {
outline : 'none' ,
backgroundColor : 'dodgerblue' ,
color : 'white' ,
} ,
} ;
const StyledItem = styled ( ContextMenu . Item , itemStyles ) ;
const StyledCheckboxItem = styled (
ContextMenu . CheckboxItem ,
itemStyles
) ;
const StyledItemIndicator = styled ( ContextMenu . ItemIndicator , {
position : 'absolute' ,
left : 5 ,
} ) ;
const StyledSeparator = styled ( ContextMenu . Separator , {
height : 1 ,
backgroundColor : 'gainsboro' ,
margin : 5 ,
} ) ;
export default ( ) => {
const [ checked , setChecked ] = React . useState ( true ) ;
return (
< ContextMenu.Root >
< ContextMenu.Trigger >
< div
style = { {
backgroundColor : 'gainsboro' ,
padding : 50 ,
textAlign : 'center' ,
} }
>
Right click anywhere
</ div >
</ ContextMenu.Trigger >
< StyledContent >
< StyledItem > About Radix UI </ StyledItem >
< StyledItem > Check for updates </ StyledItem >
< StyledSeparator />
< StyledCheckboxItem
checked = { checked }
onCheckedChange = { setChecked }
>
< StyledItemIndicator >
< CheckIcon />
</ StyledItemIndicator >
Show hidden files
</ StyledCheckboxItem >
</ StyledContent >
</ ContextMenu.Root >
) ;
} ;
Copy Use the RadioGroup
and RadioItem
parts to add an item that can be checked amongst others.
Show code
import * as ContextMenu from '@radix-ui/react-context-menu' ;
import { CheckIcon } from '@modulz/radix-icons' ;
const StyledContent = styled ( ContextMenu . Content , {
minWidth : 130 ,
backgroundColor : 'white' ,
borderRadius : 6 ,
padding : 5 ,
boxShadow : '0px 5px 15px -5px hsla(206,22%,7%,.15)' ,
} ) ;
const itemStyles = {
fontSize : 13 ,
padding : '5px 10px 5px 25px' ,
borderRadius : 3 ,
cursor : 'default' ,
position : 'relative' ,
'&:focus' : {
outline : 'none' ,
backgroundColor : 'dodgerblue' ,
color : 'white' ,
} ,
} ;
const StyledItem = styled ( ContextMenu . Item , itemStyles ) ;
const StyledRadioGroup = styled ( ContextMenu . RadioGroup , { } ) ;
const StyledRadioItem = styled ( ContextMenu . RadioItem , itemStyles ) ;
const StyledItemIndicator = styled ( ContextMenu . ItemIndicator , {
position : 'absolute' ,
left : 5 ,
} ) ;
export default ( ) => {
const [ color , setColor ] = React . useState ( 'blue' ) ;
return (
< ContextMenu.Root >
< ContextMenu.Trigger >
< div
style = { {
backgroundColor : 'gainsboro' ,
padding : 50 ,
textAlign : 'center' ,
} }
>
Right click anywhere
</ div >
</ ContextMenu.Trigger >
< StyledContent >
< StyledRadioGroup value = { color } onValueChange = { setColor } >
< StyledRadioItem value = " red " >
< StyledItemIndicator >
< CheckIcon />
</ StyledItemIndicator >
Red
</ StyledRadioItem >
< StyledRadioItem value = " blue " >
< StyledItemIndicator >
< CheckIcon />
</ StyledItemIndicator >
Blue
</ StyledRadioItem >
< StyledRadioItem value = " green " >
< StyledItemIndicator >
< CheckIcon />
</ StyledItemIndicator >
Green
</ StyledRadioItem >
</ StyledRadioGroup >
</ StyledContent >
</ ContextMenu.Root >
) ;
} ;
Copy Show code
import * as ContextMenu from '@radix-ui/react-context-menu' ;
const StyledContent = styled ( ContextMenu . Content , {
minWidth : 130 ,
backgroundColor : 'white' ,
borderRadius : 6 ,
padding : 5 ,
boxShadow : '0px 5px 15px -5px hsla(206,22%,7%,.15)' ,
} ) ;
const StyledItem = styled ( ContextMenu . Item , {
fontSize : 13 ,
padding : '5px 10px' ,
borderRadius : 3 ,
cursor : 'default' ,
'&:focus' : {
outline : 'none' ,
backgroundColor : 'dodgerblue' ,
color : 'white' ,
} ,
} ) ;
const StyledArrow = styled ( ContextMenu . Arrow , {
fill : 'white' ,
} ) ;
const Image = styled ( 'img' , {
width : 24 ,
height : 24 ,
borderRadius : 9999 ,
marginRight : 10 ,
} ) ;
export default ( ) => (
< ContextMenu.Root >
< ContextMenu.Trigger >
< div
style = { {
backgroundColor : 'gainsboro' ,
padding : 50 ,
textAlign : 'center' ,
} }
>
Right click anywhere
</ div >
</ ContextMenu.Trigger >
< StyledContent >
< StyledItem >
< Image src = " https://images.unsplash.com/photo-1463453091185-61582044d556?auto=format&fit=facearea&facepad=3&w=24&h=24&dpr=2&q=80 " />
Adolfo Hess
</ StyledItem >
< StyledItem >
< Image src = " https://images.unsplash.com/photo-1494790108377-be9c29b29330?auto=format&fit=facearea&facepad=3&w=24&h=24&dpr=2&q=80 " />
Miyah Myles
</ StyledItem >
< StyledItem >
< Image src = " https://images.unsplash.com/photo-1508186225823-0963cf9ab0de?auto=format&fit=facearea&facepad=3&w=24&h=24&dpr=2&q=80 " />
Sylvia Reynolds
</ StyledItem >
< StyledArrow />
</ StyledContent >
</ ContextMenu.Root >
) ;
Copy Key Description Space Activates the focused item. Enter Activates the focused item. ArrowDown Moves focus to the next item. ArrowUp Moves focus to the previous item. Esc Closes Content
.