mirror of
https://github.com/Unleash/unleash.git
synced 2025-01-25 00:07:47 +01:00
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)
This commit is contained in:
parent
c7842aefd0
commit
24c0976d56
@ -25,7 +25,7 @@ const StyledAvatar = styled(Avatar, {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
interface IUserAvatarProps extends AvatarProps {
|
export interface IUserAvatarProps extends AvatarProps {
|
||||||
user?: Partial<
|
user?: Partial<
|
||||||
Pick<IUser, 'id' | 'name' | 'email' | 'username' | 'imageUrl'>
|
Pick<IUser, 'id' | 'name' | 'email' | 'username' | 'imageUrl'>
|
||||||
>;
|
>;
|
||||||
@ -77,7 +77,7 @@ export const UserAvatar: FC<IUserAvatarProps> = ({
|
|||||||
sx={sx}
|
sx={sx}
|
||||||
{...props}
|
{...props}
|
||||||
data-loading
|
data-loading
|
||||||
alt='Gravatar'
|
alt={user?.name || user?.email || user?.username || 'Gravatar'}
|
||||||
src={src}
|
src={src}
|
||||||
title={title}
|
title={title}
|
||||||
onMouseEnter={onMouseEnter}
|
onMouseEnter={onMouseEnter}
|
||||||
|
@ -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<HTMLElement>): void;
|
||||||
|
};
|
||||||
|
|
||||||
|
const StyledPopover = styled(Popover)(({ theme }) => ({
|
||||||
|
pointerEvents: 'none',
|
||||||
|
'.MuiPaper-root': {
|
||||||
|
padding: theme.spacing(1),
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
const AvatarPopover = ({
|
||||||
|
mainText,
|
||||||
|
open,
|
||||||
|
anchorEl,
|
||||||
|
onPopoverClose,
|
||||||
|
}: PopoverProps) => {
|
||||||
|
return (
|
||||||
|
<StyledPopover
|
||||||
|
open={open}
|
||||||
|
anchorEl={anchorEl}
|
||||||
|
onClose={onPopoverClose}
|
||||||
|
disableScrollLock={true}
|
||||||
|
disableRestoreFocus={true}
|
||||||
|
anchorOrigin={{
|
||||||
|
vertical: 'bottom',
|
||||||
|
horizontal: 'center',
|
||||||
|
}}
|
||||||
|
transformOrigin={{
|
||||||
|
vertical: 'top',
|
||||||
|
horizontal: 'center',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<p>{mainText}</p>
|
||||||
|
</StyledPopover>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
type UserAvatarWithPopoverProps = Omit<
|
||||||
|
IUserAvatarProps,
|
||||||
|
'user' | 'onMouseEnter' | 'onMouseLeave'
|
||||||
|
> & {
|
||||||
|
user: {
|
||||||
|
name: string;
|
||||||
|
id?: number;
|
||||||
|
imageUrl?: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const UserAvatarWithPopover: FC<UserAvatarWithPopoverProps> = ({
|
||||||
|
user,
|
||||||
|
...userAvatarProps
|
||||||
|
}) => {
|
||||||
|
const [anchorEl, setAnchorEl] = useState<HTMLElement | null>(null);
|
||||||
|
const onPopoverOpen = (event: React.MouseEvent<HTMLElement>) => {
|
||||||
|
setAnchorEl(event.currentTarget);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onPopoverClose = () => {
|
||||||
|
setAnchorEl(null);
|
||||||
|
};
|
||||||
|
|
||||||
|
const avatarOpen = Boolean(anchorEl);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<UserAvatar
|
||||||
|
{...userAvatarProps}
|
||||||
|
user={user}
|
||||||
|
data-loading
|
||||||
|
onMouseEnter={(event) => {
|
||||||
|
onPopoverOpen(event);
|
||||||
|
}}
|
||||||
|
onMouseLeave={onPopoverClose}
|
||||||
|
/>
|
||||||
|
<AvatarPopover
|
||||||
|
mainText={user.name}
|
||||||
|
open={avatarOpen}
|
||||||
|
anchorEl={anchorEl}
|
||||||
|
onPopoverClose={onPopoverClose}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
@ -39,7 +39,8 @@ import {
|
|||||||
useProjectFeatureSearch,
|
useProjectFeatureSearch,
|
||||||
useProjectFeatureSearchActions,
|
useProjectFeatureSearchActions,
|
||||||
} from './useProjectFeatureSearch';
|
} from './useProjectFeatureSearch';
|
||||||
import { UserAvatar } from '../../../common/UserAvatar/UserAvatar';
|
import { UserAvatarWithPopover } from '../../../common/UserAvatar/UserAvatarWithPopover';
|
||||||
|
import type { Theme } from '@mui/material';
|
||||||
|
|
||||||
interface IPaginatedProjectFeatureTogglesProps {
|
interface IPaginatedProjectFeatureTogglesProps {
|
||||||
environments: string[];
|
environments: string[];
|
||||||
@ -176,13 +177,15 @@ export const ProjectFeatureToggles = ({
|
|||||||
header: 'By',
|
header: 'By',
|
||||||
cell: ({ row: { original } }) => {
|
cell: ({ row: { original } }) => {
|
||||||
return (
|
return (
|
||||||
<UserAvatar
|
<UserAvatarWithPopover
|
||||||
user={{
|
user={{
|
||||||
id: original.createdBy.id,
|
id: original.createdBy.id,
|
||||||
name: original.createdBy.name,
|
name: original.createdBy.name,
|
||||||
imageUrl: original.createdBy.imageUrl,
|
imageUrl: original.createdBy.imageUrl,
|
||||||
}}
|
}}
|
||||||
avatarWidth={(theme) => theme.spacing(3)}
|
avatarWidth={(theme: Theme) =>
|
||||||
|
theme.spacing(3)
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user