diff --git a/.changeset/weak-insects-sort.md b/.changeset/weak-insects-sort.md new file mode 100644 index 000000000000..cbbe7c4aa08c --- /dev/null +++ b/.changeset/weak-insects-sort.md @@ -0,0 +1,5 @@ +--- +"@rocket.chat/meteor": patch +--- + +Improving UX by change the position of room info actions buttons and menu order to avoid missclick in destructive actions. diff --git a/apps/meteor/client/components/GenericMenu/GenericMenu.spec.tsx b/apps/meteor/client/components/GenericMenu/GenericMenu.spec.tsx new file mode 100644 index 000000000000..99e62bac1a60 --- /dev/null +++ b/apps/meteor/client/components/GenericMenu/GenericMenu.spec.tsx @@ -0,0 +1,60 @@ +import '@testing-library/jest-dom'; +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import React from 'react'; + +import GenericMenu from './GenericMenu'; + +const mockedFunction = jest.fn(); +const regular = { + items: [ + { + id: 'edit', + content: 'Edit', + icon: 'pencil' as const, + onClick: mockedFunction, + }, + ], +}; +const danger = { + items: [ + { + id: 'delete', + content: 'Delete', + icon: 'trash' as const, + onClick: () => null, + variant: 'danger', + }, + ], +}; + +const sections = [regular, danger]; + +describe('Room Actions Menu', () => { + it('should render kebab menu with the list content', async () => { + render(); + + userEvent.click(screen.getByRole('button')); + + expect(await screen.findByText('Edit')).toBeInTheDocument(); + expect(await screen.findByText('Delete')).toBeInTheDocument(); + }); + + it('should have two different sections, regular and danger', async () => { + render(); + + userEvent.click(screen.getByRole('button')); + + expect(screen.getAllByRole('presentation')).toHaveLength(2); + expect(screen.getByRole('separator')).toBeInTheDocument(); + }); + + it('should call the action when item clicked', async () => { + render(); + + userEvent.click(screen.getByRole('button')); + userEvent.click(screen.getAllByRole('menuitem')[0]); + + expect(mockedFunction).toHaveBeenCalled(); + }); +}); diff --git a/apps/meteor/client/components/GenericMenu/GenericMenuItem.tsx b/apps/meteor/client/components/GenericMenu/GenericMenuItem.tsx index 44feedf86115..c01a64d708a0 100644 --- a/apps/meteor/client/components/GenericMenu/GenericMenuItem.tsx +++ b/apps/meteor/client/components/GenericMenu/GenericMenuItem.tsx @@ -13,6 +13,7 @@ export type GenericMenuItemProps = { description?: ReactNode; gap?: boolean; tooltip?: string; + variant?: string; }; const GenericMenuItem = ({ icon, content, addon, status, gap, tooltip }: GenericMenuItemProps) => ( diff --git a/apps/meteor/client/views/room/contextualBar/Info/RoomInfo/RoomInfo.tsx b/apps/meteor/client/views/room/contextualBar/Info/RoomInfo/RoomInfo.tsx index 678e5ec9f871..b0bf1d083a71 100644 --- a/apps/meteor/client/views/room/contextualBar/Info/RoomInfo/RoomInfo.tsx +++ b/apps/meteor/client/views/room/contextualBar/Info/RoomInfo/RoomInfo.tsx @@ -1,8 +1,8 @@ import type { IRoom } from '@rocket.chat/core-typings'; -import { Box, Callout, Menu, Option } from '@rocket.chat/fuselage'; +import { Box, Callout, IconButton } from '@rocket.chat/fuselage'; import { RoomAvatar } from '@rocket.chat/ui-avatar'; import { useTranslation } from '@rocket.chat/ui-contexts'; -import React, { useMemo } from 'react'; +import React from 'react'; import { ContextualbarHeader, @@ -12,9 +12,9 @@ import { ContextualbarClose, ContextualbarTitle, } from '../../../../../components/Contextualbar'; +import GenericMenu from '../../../../../components/GenericMenu/GenericMenu'; import { InfoPanel, - InfoPanelAction, InfoPanelActionGroup, InfoPanelAvatar, InfoPanelField, @@ -25,10 +25,10 @@ import { } from '../../../../../components/InfoPanel'; import RetentionPolicyCallout from '../../../../../components/InfoPanel/RetentionPolicyCallout'; import MarkdownText from '../../../../../components/MarkdownText'; -import type { Action } from '../../../../hooks/useActionSpread'; -import { useActionSpread } from '../../../../hooks/useActionSpread'; import { useRetentionPolicy } from '../../../hooks/useRetentionPolicy'; import { useRoomActions } from '../hooks/useRoomActions'; +import { useSplitRoomActions } from '../hooks/useSplitRoomActions'; +import RoomInfoActions from './RoomInfoActions'; type RoomInfoProps = { room: IRoom; @@ -47,35 +47,8 @@ const RoomInfo = ({ room, icon, onClickBack, onClickClose, onClickEnterRoom, onC const isDiscussion = 'prid' in room; const retentionPolicy = useRetentionPolicy(room); - const memoizedActions = useRoomActions(room, { onClickEnterRoom, onClickEdit }, resetState); - const { actions: actionsDefinition, menu: menuOptions } = useActionSpread(memoizedActions); - - const menu = useMemo(() => { - if (!menuOptions) { - return null; - } - - return ( -