feat: Add trigger="contextMenu" to MenuTrigger#10237
Open
devongovett wants to merge 7 commits into
Open
Conversation
|
Build successful! 🎉 |
|
Build successful! 🎉 |
## API Changes
react-aria-components/react-aria-components:ComboBoxState ComboBoxState <M extends SelectionMode = 'single', T> {
close: () => void
collection: Collection<Node<T>>
commit: () => void
commitValidation: () => void
defaultInputValue: string
defaultValue: ValueType<SelectionMode>
disabledKeys: Set<Key>
displayValidation: ValidationResult
focusStrategy: FocusStrategy | null
inputValue: string
isFocused: boolean
isOpen: boolean
open: (FocusStrategy | null, MenuTriggerAction) => void
+ point: Point | null
realtimeValidation: ValidationResult
resetValidation: () => void
revert: () => void
selectedItems: Array<Node<T>>
selectionManager: SelectionManager
setFocused: (boolean) => void
setInputValue: (string) => void
setOpen: (boolean) => void
+ setPoint: (Point) => void
setValue: (Key | readonly Array<Key> | null) => void
toggle: (FocusStrategy | null, MenuTriggerAction) => void
updateValidation: (ValidationResult) => void
value: ValueType<SelectionMode>/react-aria-components:DatePickerState DatePickerState {
close: () => void
commitValidation: () => void
dateValue: DateValue | null
defaultValue: DateValue | null
displayValidation: ValidationResult
formatValue: (string, FieldOptions) => string
getDateFormatter: (string, FormatterOptions) => DateFormatter
granularity: Granularity
hasTime: boolean
isInvalid: boolean
isOpen: boolean
open: () => void
+ point: Point | null
realtimeValidation: ValidationResult
resetValidation: () => void
setDateValue: (DateValue) => void
setOpen: (boolean) => void
+ setPoint: (Point) => void
setTimeValue: (TimeValue) => void
setValue: (DateValue | null) => void
timeValue: TimeValue | null
toggle: () => void
value: DateValue | null
}/react-aria-components:DateRangePickerState DateRangePickerState {
close: () => void
commitValidation: () => void
dateRange: RangeValue<DateValue | null> | null
defaultValue: DateRange | null
displayValidation: ValidationResult
formatValue: (string, FieldOptions) => {
start: string
end: string
} | null
getDateFormatter: (string, FormatterOptions) => DateFormatter
granularity: Granularity
hasTime: boolean
isInvalid: boolean
isOpen: boolean
open: () => void
+ point: Point | null
realtimeValidation: ValidationResult
resetValidation: () => void
setDate: ('start' | 'end', DateValue | null) => void
setDateRange: (DateRange) => void
setDateTime: ('start' | 'end', DateValue | null) => void
setOpen: (boolean) => void
+ setPoint: (Point) => void
setTime: ('start' | 'end', TimeValue | null) => void
setTimeRange: (TimeRange) => void
setValue: (DateRange | null) => void
timeRange: RangeValue<TimeValue | null> | null
updateValidation: (ValidationResult) => void
value: RangeValue<DateValue | null>
}/react-aria-components:OverlayTriggerState OverlayTriggerState {
close: () => void
isOpen: boolean
open: () => void
+ point: Point | null
setOpen: (boolean) => void
+ setPoint: (Point) => void
toggle: () => void
}/react-aria-components:RootMenuTriggerState RootMenuTriggerState {
close: () => void
closeSubmenu: (Key, number) => void
expandedKeysStack: Array<Key>
focusStrategy: FocusStrategy | null
isOpen: boolean
open: (FocusStrategy | null) => void
openSubmenu: (Key, number) => void
+ point: Point | null
setOpen: (boolean) => void
+ setPoint: (Point) => void
toggle: (FocusStrategy | null) => void
}/react-aria-components:SelectState SelectState <M extends SelectionMode = 'single', T> {
close: () => void
collection: Collection<Node<T>>
commitValidation: () => void
defaultValue: ValueType<SelectionMode>
disabledKeys: Set<Key>
displayValidation: ValidationResult
focusStrategy: FocusStrategy | null
isFocused: boolean
isOpen: boolean
open: (FocusStrategy | null) => void
+ point: Point | null
realtimeValidation: ValidationResult
resetValidation: () => void
selectedItems: Array<Node<T>>
selectionManager: SelectionManager
setFocused: (boolean) => void
setOpen: (boolean) => void
+ setPoint: (Point) => void
setValue: (Key | readonly Array<Key> | null) => void
toggle: (FocusStrategy | null) => void
updateValidation: (ValidationResult) => void
value: ValueType<SelectionMode>@react-stately/combobox/@react-stately/combobox:ComboBoxState ComboBoxState <M extends SelectionMode = 'single', T> {
close: () => void
collection: Collection<Node<T>>
commit: () => void
commitValidation: () => void
defaultInputValue: string
defaultValue: ValueType<SelectionMode>
disabledKeys: Set<Key>
displayValidation: ValidationResult
focusStrategy: FocusStrategy | null
inputValue: string
isFocused: boolean
isOpen: boolean
open: (FocusStrategy | null, MenuTriggerAction) => void
+ point: Point | null
realtimeValidation: ValidationResult
resetValidation: () => void
revert: () => void
selectedItems: Array<Node<T>>
selectionManager: SelectionManager
setFocused: (boolean) => void
setInputValue: (string) => void
setOpen: (boolean) => void
+ setPoint: (Point) => void
setValue: (Key | readonly Array<Key> | null) => void
toggle: (FocusStrategy | null, MenuTriggerAction) => void
updateValidation: (ValidationResult) => void
value: ValueType<SelectionMode>@react-stately/datepicker/@react-stately/datepicker:DatePickerState DatePickerState {
close: () => void
commitValidation: () => void
dateValue: DateValue | null
defaultValue: DateValue | null
displayValidation: ValidationResult
formatValue: (string, FieldOptions) => string
getDateFormatter: (string, FormatterOptions) => DateFormatter
granularity: Granularity
hasTime: boolean
isInvalid: boolean
isOpen: boolean
open: () => void
+ point: Point | null
realtimeValidation: ValidationResult
resetValidation: () => void
setDateValue: (DateValue) => void
setOpen: (boolean) => void
+ setPoint: (Point) => void
setTimeValue: (TimeValue) => void
setValue: (DateValue | null) => void
timeValue: TimeValue | null
toggle: () => void
value: DateValue | null
}/@react-stately/datepicker:DateRangePickerState DateRangePickerState {
close: () => void
commitValidation: () => void
dateRange: RangeValue<DateValue | null> | null
defaultValue: DateRange | null
displayValidation: ValidationResult
formatValue: (string, FieldOptions) => {
start: string
end: string
} | null
getDateFormatter: (string, FormatterOptions) => DateFormatter
granularity: Granularity
hasTime: boolean
isInvalid: boolean
isOpen: boolean
open: () => void
+ point: Point | null
realtimeValidation: ValidationResult
resetValidation: () => void
setDate: ('start' | 'end', DateValue | null) => void
setDateRange: (DateRange) => void
setDateTime: ('start' | 'end', DateValue | null) => void
setOpen: (boolean) => void
+ setPoint: (Point) => void
setTime: ('start' | 'end', TimeValue | null) => void
setTimeRange: (TimeRange) => void
setValue: (DateRange | null) => void
timeRange: RangeValue<TimeValue | null> | null
updateValidation: (ValidationResult) => void
value: RangeValue<DateValue | null>
}@react-stately/menu/@react-stately/menu:MenuTriggerState MenuTriggerState {
close: () => void
focusStrategy: FocusStrategy | null
isOpen: boolean
open: (FocusStrategy | null) => void
+ point: Point | null
setOpen: (boolean) => void
+ setPoint: (Point) => void
toggle: (FocusStrategy | null) => void
}/@react-stately/menu:RootMenuTriggerState RootMenuTriggerState {
close: () => void
closeSubmenu: (Key, number) => void
expandedKeysStack: Array<Key>
focusStrategy: FocusStrategy | null
isOpen: boolean
open: (FocusStrategy | null) => void
openSubmenu: (Key, number) => void
+ point: Point | null
setOpen: (boolean) => void
+ setPoint: (Point) => void
toggle: (FocusStrategy | null) => void
}/@react-stately/menu:SubmenuTriggerState SubmenuTriggerState {
close: () => void
closeAll: () => void
focusStrategy: FocusStrategy | null
isOpen: boolean
open: (FocusStrategy | null) => void
+ point: Point | null
+ setPoint: (Point) => void
submenuLevel: number
toggle: (FocusStrategy | null) => void
}@react-stately/overlays/@react-stately/overlays:OverlayTriggerState OverlayTriggerState {
close: () => void
isOpen: boolean
open: () => void
+ point: Point | null
setOpen: (boolean) => void
+ setPoint: (Point) => void
toggle: () => void
}@react-stately/select/@react-stately/select:SelectState SelectState <M extends SelectionMode = 'single', T> {
close: () => void
collection: Collection<Node<T>>
commitValidation: () => void
defaultValue: ValueType<SelectionMode>
disabledKeys: Set<Key>
displayValidation: ValidationResult
focusStrategy: FocusStrategy | null
isFocused: boolean
isOpen: boolean
open: (FocusStrategy | null) => void
+ point: Point | null
realtimeValidation: ValidationResult
resetValidation: () => void
selectedItems: Array<Node<T>>
selectionManager: SelectionManager
setFocused: (boolean) => void
setOpen: (boolean) => void
+ setPoint: (Point) => void
setValue: (Key | readonly Array<Key> | null) => void
toggle: (FocusStrategy | null) => void
updateValidation: (ValidationResult) => void
value: ValueType<SelectionMode> |
| let {contextMenuProps} = useContextMenu({ | ||
| onContextMenu(e) { | ||
| // eslint-disable-next-line rsp-rules/safe-event-target | ||
| let rect = e.target.getBoundingClientRect(); |
Member
There was a problem hiding this comment.
any reason not to call the safe get target?
Member
Author
There was a problem hiding this comment.
the linter is wrong. this is not a dom event. same thing happens with usePress for example.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #5020, closes #6117, closes #5387, closes #2876
Now that we have
getTargetRectsupport on Popover, it's pretty simple to add support for context menus. This PR resurrects an old branch I had with an implementation.useContextMenu– a new interaction hook. It uses the nativecontextmenuevent where possible, with fallbacks to handle keyboard and long press interactions for certain operating systems.trigger="contextMenu"prop for MenuTrigger. Stores the event's coordinates in useOverlayTriggerState, which is used in the popover'sgetTargetRect.The contextmenu event is now triggered by most browsers for keyboard events as well as mouse events. On macOS, that's Control + Enter, on Windows it's Shift + F10. However, there are some browser bugs that prevent this in some cases on macOS so we have fallback code to handle it manually. On iOS the event is not fired at all so we manually handle long press.