Skip to content

Commit

Permalink
[MA-7]: Updated the menu list structure and fixed menu not closing bug
Browse files Browse the repository at this point in the history
  • Loading branch information
ayush-chauhan233 committed Dec 9, 2024
1 parent cfb3386 commit 185c67b
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 49 deletions.
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.

import React, { useCallback, useMemo } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import React, {useCallback, useMemo} from 'react';
import {useDispatch, useSelector} from 'react-redux';

import type { Channel } from '@mattermost/types/channels';
import type { PostPriorityMetadata } from '@mattermost/types/posts';
import { PostPriority } from '@mattermost/types/posts';
import type {Channel} from '@mattermost/types/channels';
import type {PostPriorityMetadata} from '@mattermost/types/posts';
import {PostPriority} from '@mattermost/types/posts';

import { getChannel } from 'mattermost-redux/selectors/entities/channels';
import { isPostPriorityEnabled as isPostPriorityEnabledSelector } from 'mattermost-redux/selectors/entities/posts';
import { getUser } from 'mattermost-redux/selectors/entities/users';
import {getChannel} from 'mattermost-redux/selectors/entities/channels';
import {isPostPriorityEnabled as isPostPriorityEnabledSelector} from 'mattermost-redux/selectors/entities/posts';
import {getUser} from 'mattermost-redux/selectors/entities/users';

import { openModal } from 'actions/views/modals';
import {openModal} from 'actions/views/modals';

import PersistNotificationConfirmModal from 'components/persist_notification_confirm_modal';
import PostPriorityPicker from 'components/post_priority/post_priority_picker';

import Constants, { ModalIdentifiers } from 'utils/constants';
import { hasRequestedPersistentNotifications, mentionsMinusSpecialMentionsInText, specialMentionsInText } from 'utils/post_utils';
import Constants, {ModalIdentifiers} from 'utils/constants';
import {hasRequestedPersistentNotifications, mentionsMinusSpecialMentionsInText, specialMentionsInText} from 'utils/post_utils';

import type { GlobalState } from 'types/store';
import type { PostDraft } from 'types/store/draft';
import type {GlobalState} from 'types/store';
import type {PostDraft} from 'types/store/draft';

import PriorityLabels from './priority_labels';

Expand Down Expand Up @@ -62,7 +62,7 @@ const usePriority = (
return true;
}

const { priority, persistent_notifications: persistentNotifications } = draft.metadata!.priority!;
const {priority, persistent_notifications: persistentNotifications} = draft.metadata!.priority!;
if (priority !== PostPriority.URGENT || !persistentNotifications) {
return true;
}
Expand Down Expand Up @@ -97,7 +97,7 @@ const usePriority = (
updatedDraft.metadata = {};
}

handleDraftChange(updatedDraft, { instant: true });
handleDraftChange(updatedDraft, {instant: true});
focusTextbox();
}, [focusTextbox, draft, handleDraftChange]);

Expand Down
14 changes: 14 additions & 0 deletions webapp/channels/src/components/menu/menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ type MenuProps = {
onToggle?: (isOpen: boolean) => void;
onKeyDown?: (event: KeyboardEvent<HTMLDivElement>, forceCloseMenu?: () => void) => void;
width?: string;
isMenuOpen?: boolean;
}

const defaultAnchorOrigin = {vertical: 'bottom', horizontal: 'left'};
Expand Down Expand Up @@ -168,6 +169,8 @@ export function Menu(props: Props) {
onModalClose: handleMenuModalClose,
children: props.children,
onKeyDown: props.menu.onKeyDown,
menuHeader: props.menuHeader,
menuFooter: props.menuFooter,
},
}),
);
Expand Down Expand Up @@ -218,6 +221,12 @@ export function Menu(props: Props) {
}
}, [isMenuOpen]);

useEffect(() => {
if (props.menu.isMenuOpen === false) {
setAnchorElement(null);
}
}, [props.menu.isMenuOpen]);

const providerValue = useMenuContextValue(closeMenu, Boolean(anchorElement));

if (isMobileView) {
Expand All @@ -230,6 +239,7 @@ export function Menu(props: Props) {
{renderMenuButton()}
<MenuContext.Provider value={providerValue}>
<MuiPopoverStyled
aria-label={props.menu?.['aria-label'] ?? ''}
anchorEl={anchorElement}
open={isMenuOpen}
onClose={handleMenuClose}
Expand Down Expand Up @@ -271,6 +281,8 @@ interface MenuModalProps {
onModalClose: (modalId: MenuProps['id']) => void;
children: Props['children'];
onKeyDown?: MenuProps['onKeyDown'];
menuHeader?: Props['menuHeader'];
menuFooter?: Props['menuFooter'];
}

function MenuModal(props: MenuModalProps) {
Expand Down Expand Up @@ -315,7 +327,9 @@ function MenuModal(props: MenuModalProps) {
aria-labelledby={props.menuButtonId}
onClick={handleModalClickCapture}
>
{props.menuHeader}
{props.children}
{props.menuFooter}
</MuiMenuList>
</GenericModal>
</CompassDesignProvider>
Expand Down
6 changes: 4 additions & 2 deletions webapp/channels/src/components/menu/menu_item_separator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// See LICENSE.txt for license information.

import {Divider} from '@mui/material';
import type {DividerProps} from '@mui/material';
import type {ElementType} from 'react';
import React from 'react';

/**
Expand All @@ -12,11 +14,11 @@ import React from 'react';
* <Menu.Separator />
* </Menu.Container>
*/
export function MenuItemSeparator() {
export function MenuItemSeparator(props: DividerProps & {component?: ElementType }) {
return (
<Divider
role='presentation'
aria-orientation='vertical'
{...props}
/>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ import {IconContainer} from 'components/advanced_text_editor/formatting_bar/form
import CompassDesignProvider from 'components/compass_design_provider';
import * as Menu from 'components/menu';

import Constants from 'utils/constants';
import * as Keyboard from 'utils/keyboard';

import {Header, MenuItem, StyledCheckIcon, ToggleItem, StandardIcon, ImportantIcon, UrgentIcon, AcknowledgementIcon, PersistentNotificationsIcon, Footer} from './post_priority_picker_item';

import './post_priority_picker.scss';
Expand Down Expand Up @@ -84,13 +87,22 @@ function PostPriorityPicker({
requested_ack: requestedAck,
persistent_notifications: persistentNotifications,
});
onClose();
}, [onApply, onClose, persistentNotifications, priority, requestedAck]);
handleClose();
}, [onApply, handleClose, persistentNotifications, priority, requestedAck]);

const handleFooterButtonAction = useCallback((e: React.KeyboardEvent<HTMLButtonElement>, actionFn: () => void) => {
if (Keyboard.isKeyPressed(e, Constants.KeyCodes.ENTER)) {
e.preventDefault();
actionFn();
}
}, []);

const menuItems = useMemo(() => [
<MenuItem
key='menu-item-priority-standard'
id='menu-item-priority-standard'
role='menuitemradio'
aria-checked={!priority}
onClick={makeOnSelectPriority()}
trailingElements={!priority && <StyledCheckIcon size={18}/>}
leadingElement={<StandardIcon size={18}/>}
Expand All @@ -104,6 +116,8 @@ function PostPriorityPicker({
<MenuItem
key='menu-item-priority-important'
id='menu-item-priority-important'
role='menuitemradio'
aria-checked={priority === PostPriority.IMPORTANT}
onClick={makeOnSelectPriority(PostPriority.IMPORTANT)}
trailingElements={priority === PostPriority.IMPORTANT && <StyledCheckIcon size={18}/>}
leadingElement={<ImportantIcon size={18}/>}
Expand All @@ -117,6 +131,8 @@ function PostPriorityPicker({
<MenuItem
key='menu-item-priority-urgent'
id='menu-item-priority-urgent'
role='menuitemradio'
aria-checked={priority === PostPriority.URGENT}
onClick={makeOnSelectPriority(PostPriority.URGENT)}
trailingElements={priority === PostPriority.URGENT && <StyledCheckIcon size={18}/>}
leadingElement={<UrgentIcon size={18}/>}
Expand All @@ -130,7 +146,10 @@ function PostPriorityPicker({
], [makeOnSelectPriority, priority]);

const menuCheckboxItems = useMemo(() => (postAcknowledgementsEnabled || persistentNotificationsEnabled ? [
<Menu.Separator key='menu-item-checkbox-separator'/>,
<Menu.Separator
key='menu-item-checkbox-separator'
component='li'
/>,
postAcknowledgementsEnabled ? (
<ToggleItem
key='post_priority.requested_ack.item'
Expand Down Expand Up @@ -178,28 +197,33 @@ function PostPriorityPicker({
] : []), [formatMessage, handleAck, handlePersistentNotifications, interval, persistentNotifications, persistentNotificationsEnabled, postAcknowledgementsEnabled, priority, requestedAck]);

const footer = useMemo(() => postAcknowledgementsEnabled &&
<Footer key='footer'>
<button
type='button'
className='PostPriorityPicker__cancel'
onClick={handleClose}
>
<FormattedMessage
id='post_priority.picker.cancel'
defaultMessage='Cancel'
/>
</button>
<button
type='button'
className='PostPriorityPicker__apply'
onClick={handleApply}
>
<FormattedMessage
id='post_priority.picker.apply'
defaultMessage='Apply'
/>
</button>
</Footer>, [handleApply, handleClose, postAcknowledgementsEnabled]);
<div>
<Menu.Separator/>
<Footer key='footer'>
<button
type='submit'
className='PostPriorityPicker__cancel'
onClick={handleClose}
onKeyDown={(e) => handleFooterButtonAction(e, handleClose)}
>
<FormattedMessage
id='post_priority.picker.cancel'
defaultMessage='Cancel'
/>
</button>
<button
type='submit'
className='PostPriorityPicker__apply'
onClick={handleApply}
onKeyDown={(e) => handleFooterButtonAction(e, handleApply)}
>
<FormattedMessage
id='post_priority.picker.apply'
defaultMessage='Apply'
/>
</button>
</Footer>
</div>, [handleApply, handleClose, handleFooterButtonAction, postAcknowledgementsEnabled]);

return (<CompassDesignProvider theme={theme}>
<Menu.Container
Expand All @@ -224,22 +248,24 @@ function PostPriorityPicker({
id: 'post.priority.dropdown',
'aria-label': 'Post priority options',
width: 'max-content',
onToggle: setPickerOpen,
isMenuOpen: pickerOpen,
}}
menuButtonTooltip={{
id: 'postPriorityPickerOverlayTooltip',
text: messagePriority,

}}
menuHeader={
<>
<div>
<Header className='modal-title'>
{formatMessage({
id: 'post_priority.picker.header',
defaultMessage: 'Message priority',
})}
</Header>
<Menu.Separator/>
</>
</div>
}
anchorOrigin={{
vertical: 'top',
Expand All @@ -249,11 +275,7 @@ function PostPriorityPicker({
vertical: 'bottom',
horizontal: 'center',
}}
menuFooter={
<>
<Menu.Separator/>
{footer}
</>}
menuFooter={footer}
>
{
[...menuItems, ...menuCheckboxItems]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,9 @@ function ToggleItem({
disabled={disabled}
leadingElement={icon}
tabIndex={-1}
role='menuitemcheckbox'
aria-checked={toggled}
aria-label={ariaLabel}
trailingElements={<>
<Toggle
ariaLabel={ariaLabel}
Expand All @@ -121,6 +124,7 @@ function ToggleItem({
onToggle={onClick}
toggled={toggled}
toggleClassName='btn-toggle-primary'
tabIndex={-1}
/>
</>}
labels={<>
Expand Down
3 changes: 3 additions & 0 deletions webapp/channels/src/components/toggle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ type Props = {
size?: 'btn-lg' | 'btn-md' |'btn-sm';
toggleClassName?: string;
ariaLabel?: string;
tabIndex?: number;
}

const Toggle: React.FC<Props> = (props: Props) => {
Expand All @@ -29,6 +30,7 @@ const Toggle: React.FC<Props> = (props: Props) => {
ariaLabel,
size = 'btn-lg',
toggleClassName = 'btn-toggle',
tabIndex = 0,
} = props;
let dataTestId = `${id}-button`;
if (overrideTestId) {
Expand All @@ -55,6 +57,7 @@ const Toggle: React.FC<Props> = (props: Props) => {
className={className}
aria-pressed={toggled ? 'true' : 'false'}
disabled={disabled}
tabIndex={tabIndex}
>
<div className='handle'/>
{text(toggled, onText, offText)}
Expand Down

0 comments on commit 185c67b

Please sign in to comment.