From 24c0976d5611b22249497ae330ad906f0abd0113 Mon Sep 17 00:00:00 2001 From: Thomas Heartman Date: Tue, 11 Jun 2024 09:40:48 +0200 Subject: [PATCH] feat: add popover to users in flags list (#7344) This PR adds a popover to the user avatars in the flag list. The popover is similar to the one used for projects and groups, but it differs in a few ways: - There's less padding. There's quite a lot of padding in the other popovers, and it felt like too much for this table. - It only shows one bit of text (the user's name/username/email). The other popovers show email and name/username, but we don't have all that information, so this is a stripped down version. Flag list popover: ![image](https://github.com/Unleash/unleash/assets/17786332/6a86f638-ba6d-48e0-87e2-078b582697cf) Group popover: ![image](https://github.com/Unleash/unleash/assets/17786332/d5fc7172-8fcb-4fac-87c4-05f211c0938c) or if no email ![image](https://github.com/Unleash/unleash/assets/17786332/51955ead-849f-4bfc-81aa-e1852677647c) --- .../common/UserAvatar/UserAvatar.tsx | 4 +- .../UserAvatar/UserAvatarWithPopover.tsx | 92 +++++++++++++++++++ .../ProjectFeatureToggles.tsx | 9 +- 3 files changed, 100 insertions(+), 5 deletions(-) create mode 100644 frontend/src/component/common/UserAvatar/UserAvatarWithPopover.tsx diff --git a/frontend/src/component/common/UserAvatar/UserAvatar.tsx b/frontend/src/component/common/UserAvatar/UserAvatar.tsx index 69f2ce4020..ae4732398c 100644 --- a/frontend/src/component/common/UserAvatar/UserAvatar.tsx +++ b/frontend/src/component/common/UserAvatar/UserAvatar.tsx @@ -25,7 +25,7 @@ const StyledAvatar = styled(Avatar, { }; }); -interface IUserAvatarProps extends AvatarProps { +export interface IUserAvatarProps extends AvatarProps { user?: Partial< Pick >; @@ -77,7 +77,7 @@ export const UserAvatar: FC = ({ sx={sx} {...props} data-loading - alt='Gravatar' + alt={user?.name || user?.email || user?.username || 'Gravatar'} src={src} title={title} onMouseEnter={onMouseEnter} diff --git a/frontend/src/component/common/UserAvatar/UserAvatarWithPopover.tsx b/frontend/src/component/common/UserAvatar/UserAvatarWithPopover.tsx new file mode 100644 index 0000000000..8796e7f93b --- /dev/null +++ b/frontend/src/component/common/UserAvatar/UserAvatarWithPopover.tsx @@ -0,0 +1,92 @@ +import { styled, Popover } from '@mui/material'; +import { useState, type FC } from 'react'; +import type React from 'react'; +import { type IUserAvatarProps, UserAvatar } from './UserAvatar'; + +type PopoverProps = { + mainText: string; + open: boolean; + anchorEl: HTMLElement | null; + onPopoverClose(event: React.MouseEvent): void; +}; + +const StyledPopover = styled(Popover)(({ theme }) => ({ + pointerEvents: 'none', + '.MuiPaper-root': { + padding: theme.spacing(1), + }, +})); + +const AvatarPopover = ({ + mainText, + open, + anchorEl, + onPopoverClose, +}: PopoverProps) => { + return ( + +

{mainText}

+
+ ); +}; + +type UserAvatarWithPopoverProps = Omit< + IUserAvatarProps, + 'user' | 'onMouseEnter' | 'onMouseLeave' +> & { + user: { + name: string; + id?: number; + imageUrl?: string; + }; +}; + +export const UserAvatarWithPopover: FC = ({ + user, + ...userAvatarProps +}) => { + const [anchorEl, setAnchorEl] = useState(null); + const onPopoverOpen = (event: React.MouseEvent) => { + setAnchorEl(event.currentTarget); + }; + + const onPopoverClose = () => { + setAnchorEl(null); + }; + + const avatarOpen = Boolean(anchorEl); + + return ( + <> + { + onPopoverOpen(event); + }} + onMouseLeave={onPopoverClose} + /> + + + ); +}; diff --git a/frontend/src/component/project/Project/PaginatedProjectFeatureToggles/ProjectFeatureToggles.tsx b/frontend/src/component/project/Project/PaginatedProjectFeatureToggles/ProjectFeatureToggles.tsx index cee05ff05f..ac8df912f6 100644 --- a/frontend/src/component/project/Project/PaginatedProjectFeatureToggles/ProjectFeatureToggles.tsx +++ b/frontend/src/component/project/Project/PaginatedProjectFeatureToggles/ProjectFeatureToggles.tsx @@ -39,7 +39,8 @@ import { useProjectFeatureSearch, useProjectFeatureSearchActions, } from './useProjectFeatureSearch'; -import { UserAvatar } from '../../../common/UserAvatar/UserAvatar'; +import { UserAvatarWithPopover } from '../../../common/UserAvatar/UserAvatarWithPopover'; +import type { Theme } from '@mui/material'; interface IPaginatedProjectFeatureTogglesProps { environments: string[]; @@ -176,13 +177,15 @@ export const ProjectFeatureToggles = ({ header: 'By', cell: ({ row: { original } }) => { return ( - theme.spacing(3)} + avatarWidth={(theme: Theme) => + theme.spacing(3) + } /> ); },