mirror of
https://github.com/bulwarkmail/webmail.git
synced 2026-10-31 00:12:39 +00:00
feat: open a calendar event's menu with Shift+F10
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { render, screen, cleanup } from '@testing-library/react';
|
||||
import { describe, it, expect, afterEach, beforeEach } from 'vitest';
|
||||
import { render, screen, cleanup, fireEvent } from '@testing-library/react';
|
||||
import { describe, it, expect, afterEach, beforeEach, vi } from 'vitest';
|
||||
import { EventCard } from '../event-card';
|
||||
import { useSettingsStore } from '@/stores/settings-store';
|
||||
import type { Calendar, CalendarEvent, CalendarParticipant } from '@/lib/jmap/types';
|
||||
@@ -139,3 +139,20 @@ describe('EventCard colour settings', () => {
|
||||
expect(calendar.color).toBe('#22c55e');
|
||||
});
|
||||
});
|
||||
|
||||
describe('EventCard from the keyboard (MA-05)', () => {
|
||||
afterEach(cleanup);
|
||||
|
||||
it.each(['chip', 'span', 'block'] as const)('opens the event menu with Shift+F10 on the %s', (variant) => {
|
||||
const onContextMenu = vi.fn();
|
||||
const event = makeOccurrence('a', 'accepted');
|
||||
render(<EventCard event={event} variant={variant} onContextMenu={onContextMenu} currentUserEmails={me} />);
|
||||
const card = screen.getByRole('button');
|
||||
fireEvent.keyDown(card, { key: 'F10' });
|
||||
expect(onContextMenu).not.toHaveBeenCalled();
|
||||
fireEvent.keyDown(card, { key: 'F10', shiftKey: true });
|
||||
expect(onContextMenu).toHaveBeenCalledOnce();
|
||||
expect(onContextMenu.mock.calls[0][1]).toBe(event);
|
||||
expect(onContextMenu.mock.calls[0][0].currentTarget).toBe(card);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -191,6 +191,21 @@ export function EventCard({ event, calendar, variant, onClick, onMouseEnter, onM
|
||||
preventDefault: () => {}, stopPropagation: () => {},
|
||||
} as unknown as React.MouseEvent, event);
|
||||
}, !!onContextMenu);
|
||||
// Shift+F10 opens the same menu from the keyboard (the menu key already
|
||||
// fires contextmenu by itself). Prevented here, so a browser that also
|
||||
// turns Shift+F10 into a contextmenu event doesn't open it twice.
|
||||
const handleKeyDown = onContextMenu ? (e: React.KeyboardEvent<HTMLElement>) => {
|
||||
if (!(e.shiftKey && e.key === "F10")) return;
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
const target = e.currentTarget;
|
||||
const rect = target.getBoundingClientRect();
|
||||
onContextMenu({
|
||||
type: "contextmenu", clientX: rect.left, clientY: rect.bottom, detail: 0, currentTarget: target, target,
|
||||
preventDefault: () => {}, stopPropagation: () => {},
|
||||
} as unknown as React.MouseEvent, event);
|
||||
} : undefined;
|
||||
|
||||
const touchProps = onContextMenu ? {
|
||||
onTouchStart: (e: React.TouchEvent<HTMLElement>) => { pressedRef.current = e.currentTarget; longPress.onTouchStart(e); },
|
||||
onTouchMove: longPress.onTouchMove,
|
||||
@@ -205,6 +220,7 @@ export function EventCard({ event, calendar, variant, onClick, onMouseEnter, onM
|
||||
onMouseEnter={(e) => onMouseEnter?.(e.currentTarget.getBoundingClientRect())}
|
||||
onMouseLeave={() => onMouseLeave?.()}
|
||||
onContextMenu={handleContextMenu}
|
||||
onKeyDown={handleKeyDown}
|
||||
{...touchProps}
|
||||
aria-label={ariaLabel}
|
||||
tabIndex={tabbable ? undefined : -1}
|
||||
@@ -236,6 +252,7 @@ export function EventCard({ event, calendar, variant, onClick, onMouseEnter, onM
|
||||
onMouseEnter={(e) => onMouseEnter?.(e.currentTarget.getBoundingClientRect())}
|
||||
onMouseLeave={() => onMouseLeave?.()}
|
||||
onContextMenu={handleContextMenu}
|
||||
onKeyDown={handleKeyDown}
|
||||
{...touchProps}
|
||||
aria-label={ariaLabel}
|
||||
tabIndex={tabbable ? undefined : -1}
|
||||
@@ -270,6 +287,7 @@ export function EventCard({ event, calendar, variant, onClick, onMouseEnter, onM
|
||||
onMouseEnter={(e) => onMouseEnter?.(e.currentTarget.getBoundingClientRect())}
|
||||
onMouseLeave={() => onMouseLeave?.()}
|
||||
onContextMenu={handleContextMenu}
|
||||
onKeyDown={handleKeyDown}
|
||||
{...touchProps}
|
||||
aria-label={ariaLabel}
|
||||
tabIndex={tabbable ? undefined : -1}
|
||||
|
||||
Reference in New Issue
Block a user