Toggle context menus on click and add active state

This commit is contained in:
Sylvan Mably 2024-03-10 14:14:22 -04:00
parent 3eed6cb350
commit a5497fcab8
9 changed files with 47 additions and 26 deletions

View file

@ -195,6 +195,15 @@
} }
} }
&:active {
@include light-theme {
background: $color-gray-20;
}
@include dark-theme {
background: $color-gray-62;
}
}
&:focus { &:focus {
outline: none; outline: none;
@include keyboard-mode { @include keyboard-mode {

View file

@ -207,10 +207,11 @@ export function CallsTab({
}} }}
portalToRoot portalToRoot
> >
{({ openMenu, onKeyDown }) => { {({ onClick, onKeyDown, ref }) => {
return ( return (
<NavSidebarActionButton <NavSidebarActionButton
onClick={openMenu} ref={ref}
onClick={onClick}
onKeyDown={onKeyDown} onKeyDown={onKeyDown}
icon={<span className="CallsTab__MoreActionsIcon" />} icon={<span className="CallsTab__MoreActionsIcon" />}
label={i18n('icu:CallsTab__MoreActionsLabel')} label={i18n('icu:CallsTab__MoreActionsLabel')}

View file

@ -25,7 +25,7 @@ export type ContextMenuOptionType<T> = Readonly<{
}>; }>;
type RenderButtonProps = Readonly<{ type RenderButtonProps = Readonly<{
openMenu: (ev: React.MouseEvent) => void; onClick: (ev: React.MouseEvent) => void;
onKeyDown: (ev: KeyboardEvent) => void; onKeyDown: (ev: KeyboardEvent) => void;
isMenuShowing: boolean; isMenuShowing: boolean;
ref: React.Ref<HTMLButtonElement> | null; ref: React.Ref<HTMLButtonElement> | null;
@ -207,10 +207,15 @@ export function ContextMenu<T>({
}; };
const handleClick = (ev: React.MouseEvent) => { const handleClick = (ev: React.MouseEvent) => {
closeCurrentOpenContextMenu?.(); if (isMenuShowing && ev.type !== 'contextmenu') {
closeCurrentOpenContextMenu = () => setIsMenuShowing(false); setIsMenuShowing(false);
virtualElement.current = generateVirtualElement(ev.clientX, ev.clientY); closeCurrentOpenContextMenu = undefined;
setIsMenuShowing(true); } else {
closeCurrentOpenContextMenu?.();
closeCurrentOpenContextMenu = () => setIsMenuShowing(false);
virtualElement.current = generateVirtualElement(ev.clientX, ev.clientY);
setIsMenuShowing(true);
}
ev.stopPropagation(); ev.stopPropagation();
ev.preventDefault(); ev.preventDefault();
}; };
@ -316,7 +321,7 @@ export function ContextMenu<T>({
buttonNode = ( buttonNode = (
<> <>
{(children as (props: RenderButtonProps) => JSX.Element)({ {(children as (props: RenderButtonProps) => JSX.Element)({
openMenu: onClick || handleClick, onClick: onClick || handleClick,
onKeyDown: handleKeyDown, onKeyDown: handleKeyDown,
isMenuShowing, isMenuShowing,
ref: setReferenceElement, ref: setReferenceElement,

View file

@ -668,10 +668,11 @@ export function LeftPane({
}} }}
portalToRoot portalToRoot
> >
{({ openMenu, onKeyDown }) => { {({ onClick, onKeyDown, ref }) => {
return ( return (
<NavSidebarActionButton <NavSidebarActionButton
onClick={openMenu} ref={ref}
onClick={onClick}
onKeyDown={onKeyDown} onKeyDown={onKeyDown}
icon={<span className="module-left-pane__moreActionsIcon" />} icon={<span className="module-left-pane__moreActionsIcon" />}
label="More Actions" label="More Actions"

View file

@ -16,19 +16,23 @@ import {
import { WidthBreakpoint, getNavSidebarWidthBreakpoint } from './_util'; import { WidthBreakpoint, getNavSidebarWidthBreakpoint } from './_util';
import type { UnreadStats } from '../util/countUnreadStats'; import type { UnreadStats } from '../util/countUnreadStats';
export function NavSidebarActionButton({ type NavSidebarActionButtonProps = {
icon,
label,
onClick,
onKeyDown,
}: {
icon: ReactNode; icon: ReactNode;
label: ReactNode; label: ReactNode;
onClick: MouseEventHandler<HTMLButtonElement>; onClick: MouseEventHandler<HTMLButtonElement>;
onKeyDown?: KeyboardEventHandler<HTMLButtonElement>; onKeyDown?: KeyboardEventHandler<HTMLButtonElement>;
}): JSX.Element { };
export const NavSidebarActionButton = React.forwardRef<
HTMLButtonElement,
NavSidebarActionButtonProps
>(function NavSidebarActionButtonInner(
{ icon, label, onClick, onKeyDown },
ref
): JSX.Element {
return ( return (
<button <button
ref={ref}
type="button" type="button"
className="NavSidebar__ActionButton" className="NavSidebar__ActionButton"
onClick={onClick} onClick={onClick}
@ -38,7 +42,7 @@ export function NavSidebarActionButton({
<span className="NavSidebar__ActionButtonLabel">{label}</span> <span className="NavSidebar__ActionButtonLabel">{label}</span>
</button> </button>
); );
} });
export type NavSidebarProps = Readonly<{ export type NavSidebarProps = Readonly<{
actions?: ReactNode; actions?: ReactNode;

View file

@ -307,7 +307,7 @@ export function NavTabs({
}} }}
portalToRoot portalToRoot
> >
{({ openMenu, onKeyDown, ref }) => { {({ onClick, onKeyDown, ref }) => {
return ( return (
<button <button
type="button" type="button"
@ -319,7 +319,7 @@ export function NavTabs({
}} }}
onClick={event => { onClick={event => {
if (hasPendingUpdate) { if (hasPendingUpdate) {
openMenu(event); onClick(event);
} else { } else {
onShowSettings(); onShowSettings();
} }

View file

@ -923,14 +923,14 @@ export function SendStoryModal({
}} }}
theme={theme === ThemeType.dark ? Theme.Dark : Theme.Light} theme={theme === ThemeType.dark ? Theme.Dark : Theme.Light}
> >
{({ openMenu, onKeyDown, ref, menuNode }) => ( {({ onClick, onKeyDown, ref, menuNode }) => (
<div> <div>
<Button <Button
ref={ref} ref={ref}
className="SendStoryModal__new-story__button" className="SendStoryModal__new-story__button"
variant={ButtonVariant.Secondary} variant={ButtonVariant.Secondary}
size={ButtonSize.Small} size={ButtonSize.Small}
onClick={openMenu} onClick={onClick}
onKeyDown={onKeyDown} onKeyDown={onKeyDown}
> >
{i18n('icu:SendStoryModal__new')} {i18n('icu:SendStoryModal__new')}

View file

@ -174,10 +174,11 @@ export function StoriesTab({
}} }}
portalToRoot portalToRoot
> >
{({ openMenu, onKeyDown }) => { {({ onClick, onKeyDown, ref }) => {
return ( return (
<NavSidebarActionButton <NavSidebarActionButton
onClick={openMenu} ref={ref}
onClick={onClick}
onKeyDown={onKeyDown} onKeyDown={onKeyDown}
icon={<span className="StoriesTab__MoreActionsIcon" />} icon={<span className="StoriesTab__MoreActionsIcon" />}
label={i18n('icu:StoriesTab__MoreActionsLabel')} label={i18n('icu:StoriesTab__MoreActionsLabel')}

View file

@ -642,9 +642,9 @@ function ReplyOrReactionMessage({
return reply.author.isMe && !reply.deletedForEveryone ? ( return reply.author.isMe && !reply.deletedForEveryone ? (
<ContextMenu i18n={i18n} key={reply.id} menuOptions={menuOptions}> <ContextMenu i18n={i18n} key={reply.id} menuOptions={menuOptions}>
{({ openMenu, menuNode }) => ( {({ onClick, menuNode }) => (
<> <>
{renderContent(openMenu)} {renderContent(onClick)}
{menuNode} {menuNode}
</> </>
)} )}