This component shows a dropdown menu on desktop devices by triggering the context menu
event. Is it possible to use this dropdown component on touch devices, but instead of the context menu
event, display the dropdown with long press
? There are no context menu
events on touch devices.
I want to display a dropdown with a
long press
technique.
import React from 'react';
import type { MenuProps } from 'antd';
import { Dropdown, theme } from 'antd';
const items: MenuProps['items'] = [
{
label: '1st menu item',
key: '1',
},
{
label: '2nd menu item',
key: '2',
},
{
label: '3rd menu item',
key: '3',
},
];
const App: React.FC = () => {
const {
token: { colorBgLayout, colorTextTertiary },
} = theme.useToken();
return (
<Dropdown menu={{ items }} trigger={['contextMenu']}>
<div
style={{
color: colorTextTertiary,
background: colorBgLayout,
height: 200,
textAlign: 'center',
lineHeight: '200px',
}}
>
Right Click on here
</div>
</Dropdown>
);
};
export default App;
I tried to wrap the content with extra div and apply touch events on it. Is it a correct approach or maybe there is some built-in solution?
<div
onTouchStart={handleTouchStart}
onTouchEnd={handleTouchEnd}
onContextMenu={e => e.preventDefault()}
>
Right Click on here or Long Press on Touch Devices
</div>
Dropdown pass 4 props to it's children when trigger is set to contextMenu
I try pointerDown and pointerUp event instead of onTouchEvent (antd throw error. It may be some field/value missing from onTouchEvent). You can use pointer down and up events to detect long press and call onContextMenu function to open context menu.
Here's the complete code:
import type { MenuProps } from 'antd';
import { Dropdown, theme } from 'antd';
import type React from 'react';
import { type ForwardedRef, forwardRef, useRef } from 'react';
const items: MenuProps['items'] = [
{
label: '1st menu item',
key: '1'
},
{
label: '2nd menu item',
key: '2'
},
{
label: '3rd menu item',
key: '3'
}
];
const App: React.FC = () => {
return (
<Dropdown menu={{ items }} trigger={['contextMenu']}>
<Content />
</Dropdown>
);
};
export default App;
interface ContentProps {
onClick?: () => void;
onContextMenu?: (e: React.MouseEvent) => void;
className?: string;
// if disabled is true, onContextMenu and onClick events are not available
disabled?: boolean;
}
const Content = forwardRef((props: ContentProps, ref: ForwardedRef<HTMLDivElement>) => {
const { onContextMenu, className, disabled } = props;
const {
token: { colorBgLayout, colorTextTertiary }
} = theme.useToken();
const timer = useRef<ReturnType<typeof setTimeout>>(null);
const clearTimer = () => {
if (timer.current) {
clearTimeout(timer.current);
timer.current = null;
}
};
return (
<div
ref={ref}
style={{
color: colorTextTertiary,
background: colorBgLayout,
height: 200,
textAlign: 'center',
lineHeight: '200px'
}}
className={className}
onContextMenu={onContextMenu}
onPointerDown={(e) => {
if (disabled || e.pointerType !== 'touch') {
return;
}
// Clear timer if it is already running
clearTimer();
timer.current = setTimeout(() => {
onContextMenu?.(e);
clearTimer();
}, 2000);
}}
onPointerUp={clearTimer}
>
Right Click on here or Long Press on Touch Devices
</div>
);
});