MM-53999 Fix keyboard support for Menu components (#24282)

* Cherry-pick test changes from #24243

* Add required change from Saturn's PR to make reminder menu accessible

* MM-53999 Flip provider order so that MUI props are passed

* MM-53999 Pass MUI props through custom MenuItem components

* Address feedback

* Update snapshots
Этот коммит содержится в:
Harrison Healey
2023-08-22 12:53:02 -04:00
коммит произвёл GitHub
родитель e48efdc5da
Коммит e2a5293e2e
17 изменённых файлов: 292 добавлений и 76 удалений

Просмотреть файл

@@ -184,15 +184,6 @@ exports[`components/dot_menu/DotMenu should match snapshot, on Center 1`] = `
/>
}
/>
<Connect(ChannelPermissionGate)
channelId=""
permissions={
Array [
"add_reaction",
]
}
teamId="team_id_1"
/>
<MenuItem
data-testid="follow_post_thread_post_id_1"
id="follow_post_thread_post_id_1"

Просмотреть файл

@@ -508,12 +508,12 @@ export class DotMenuClass extends React.PureComponent<Props, State> {
onClick={this.handleForwardMenuItemActivated}
/>
}
<ChannelPermissionGate
channelId={this.props.post.channel_id}
teamId={this.props.teamId}
permissions={[Permissions.ADD_REACTION]}
>
{Boolean(isMobile && !isSystemMessage && !this.props.isReadOnly && this.props.enableEmojiPicker) &&
{Boolean(isMobile && !isSystemMessage && !this.props.isReadOnly && this.props.enableEmojiPicker) &&
<ChannelPermissionGate
channelId={this.props.post.channel_id}
teamId={this.props.teamId}
permissions={[Permissions.ADD_REACTION]}
>
<Menu.Item
id={`post_reaction_${this.props.post.id}`}
data-testid={`post_reaction_${this.props.post.id}`}
@@ -526,8 +526,8 @@ export class DotMenuClass extends React.PureComponent<Props, State> {
leadingElement={<EmoticonPlusOutlineIcon size={18}/>}
onClick={this.handleAddReactionMenuItemActivated}
/>
}
</ChannelPermissionGate>
</ChannelPermissionGate>
}
{Boolean(
!isSystemMessage &&
this.props.isCollapsedThreadsEnabled &&

Просмотреть файл

@@ -144,6 +144,10 @@ function PostReminderSubmenu(props: Props) {
return (
<Menu.SubMenu
id={`remind_post_${props.post.id}`}
menuAriaLabel={formatMessage({
id: 'post_info.post_reminder.sub_menu.header',
defaultMessage: 'Set a reminder for:',
})}
labels={
<FormattedMessage
id='post_info.post_reminder.menu'

Просмотреть файл

@@ -226,32 +226,32 @@ export function Menu(props: Props) {
return (
<CompassDesignProvider theme={theme}>
{renderMenuButton()}
<MuiMenuStyled
anchorEl={anchorElement}
open={isMenuOpen}
onClose={handleMenuClose}
onClick={handleMenuClick}
onKeyDown={handleMenuKeyDown}
className={A11yClassNames.POPUP}
width={props.menu.width}
disableAutoFocusItem={disableAutoFocusItem} // This is not anti-pattern, see handleMenuButtonMouseDown
MenuListProps={{
id: props.menu.id,
'aria-label': props.menu?.['aria-label'] ?? '',
}}
TransitionProps={{
mountOnEnter: true,
unmountOnExit: true,
timeout: {
enter: MENU_OPEN_ANIMATION_DURATION,
exit: MENU_CLOSE_ANIMATION_DURATION,
},
}}
>
<MenuContext.Provider value={providerValue}>
<MenuContext.Provider value={providerValue}>
<MuiMenuStyled
anchorEl={anchorElement}
open={isMenuOpen}
onClose={handleMenuClose}
onClick={handleMenuClick}
onKeyDown={handleMenuKeyDown}
className={A11yClassNames.POPUP}
width={props.menu.width}
disableAutoFocusItem={disableAutoFocusItem} // This is not anti-pattern, see handleMenuButtonMouseDown
MenuListProps={{
id: props.menu.id,
'aria-label': props.menu?.['aria-label'] ?? '',
}}
TransitionProps={{
mountOnEnter: true,
unmountOnExit: true,
timeout: {
enter: MENU_OPEN_ANIMATION_DURATION,
exit: MENU_CLOSE_ANIMATION_DURATION,
},
}}
>
{props.children}
</MenuContext.Provider>
</MuiMenuStyled>
</MuiMenuStyled>
</MenuContext.Provider>
</CompassDesignProvider>
);
}

Просмотреть файл

@@ -93,10 +93,19 @@ export interface Props extends MuiMenuItemProps {
* To be used as a child of Menu component.
* Checkout Compass's Menu Item(compass.mattermost.com) for terminology, styling and usage guidelines.
*
* @example
* @example <caption>Using a menu in a component</caption>
* <Menu.Container>
* <Menu.Item/>
* <Menu.Item/>
* </Menu.Container>
* @example <caption>Wrapping a menu item in another component</caption>
* // Remember to pass all unused props into the Menu.Item to ensure MUI props for a11y are passed properly
* const ConsoleLogItem = ({message, ...otherProps}) => ({
* <Menu.Item
* onClick={() => console.log(message)}
* {...otherProps}
* />
* });
*
*/
export function MenuItem(props: Props) {
const {
@@ -107,7 +116,7 @@ export function MenuItem(props: Props) {
isLabelsRowLayout,
children,
onClick,
...restProps
...otherProps
} = props;
const menuContext = useContext(MenuContext);
@@ -181,7 +190,7 @@ export function MenuItem(props: Props) {
isLabelsRowLayout={isLabelsRowLayout}
onKeyDown={handleClick}
onMouseDown={handleClick}
{...restProps}
{...otherProps}
>
{leadingElement && <div className='leading-element'>{leadingElement}</div>}
<div className='label-elements'>{labels}</div>
@@ -240,7 +249,7 @@ const MenuItemStyled = styled(MuiMenuItem, {
'&.Mui-focusVisible .label-elements>:last-child, &.Mui-focusVisible .label-elements>:first-child, &.Mui-focusVisible .label-elements>:only-child': {
color: isDestructive && 'var(--button-color)',
},
'&.Mui-focusVisible .leading-element': {
'&.Mui-focusVisible .leading-element, &.Mui-focusVisible .trailing-elements': {
color: isDestructive && 'var(--button-color)',
},

Просмотреть файл

@@ -19,6 +19,7 @@ type Props = {
const CreateNewCategoryMenuItem = ({
id,
...otherProps
}: Props) => {
const dispatch = useDispatch();
const handleCreateCategory = useCallback(() => {
@@ -41,6 +42,7 @@ const CreateNewCategoryMenuItem = ({
defaultMessage='Create New Category'
/>
)}
{...otherProps}
/>
);
};

Просмотреть файл

@@ -11,16 +11,17 @@ import {openModal} from 'actions/views/modals';
import {ModalIdentifiers} from 'utils/constants';
import MarkAsReadConfirmModal from './mark_as_read_confirm_modal';
type Props = ({
type Props = {
id: string;
handleViewCategory: () => void;
numChannels: number;
})
}
const MarkAsUnreadItem = ({
id,
handleViewCategory,
numChannels,
...otherProps
}: Props) => {
const dispatch = useDispatch();
@@ -56,6 +57,7 @@ const MarkAsUnreadItem = ({
defaultMessage='Mark category as read'
/>
)}
{...otherProps}
/>
);
};