From 23aa5c6f94553c98affa4c05c8208a495f891525 Mon Sep 17 00:00:00 2001 From: Ajay Bura <32841439+ajbura@users.noreply.github.com> Date: Sun, 24 Aug 2025 18:06:45 +0530 Subject: [PATCH] Add option to view user avatar (#2462) --- src/app/components/user-avatar/UserAvatar.tsx | 8 +-- src/app/components/user-profile/UserHero.tsx | 53 +++++++++++++++++-- src/app/components/user-profile/styles.css.ts | 12 +++++ 3 files changed, 66 insertions(+), 7 deletions(-) diff --git a/src/app/components/user-avatar/UserAvatar.tsx b/src/app/components/user-avatar/UserAvatar.tsx index 98067ad4..d9de9b79 100644 --- a/src/app/components/user-avatar/UserAvatar.tsx +++ b/src/app/components/user-avatar/UserAvatar.tsx @@ -1,15 +1,17 @@ import { AvatarFallback, AvatarImage, color } from 'folds'; import React, { ReactEventHandler, ReactNode, useState } from 'react'; +import classNames from 'classnames'; import * as css from './UserAvatar.css'; import colorMXID from '../../../util/colorMXID'; type UserAvatarProps = { + className?: string; userId: string; src?: string; alt?: string; renderFallback: () => ReactNode; }; -export function UserAvatar({ userId, src, alt, renderFallback }: UserAvatarProps) { +export function UserAvatar({ className, userId, src, alt, renderFallback }: UserAvatarProps) { const [error, setError] = useState(false); const handleLoad: ReactEventHandler = (evt) => { @@ -20,7 +22,7 @@ export function UserAvatar({ userId, src, alt, renderFallback }: UserAvatarProps return ( {renderFallback()} @@ -29,7 +31,7 @@ export function UserAvatar({ userId, src, alt, renderFallback }: UserAvatarProps return ( setError(true)} diff --git a/src/app/components/user-profile/UserHero.tsx b/src/app/components/user-profile/UserHero.tsx index cf4c815f..0e7fb748 100644 --- a/src/app/components/user-profile/UserHero.tsx +++ b/src/app/components/user-profile/UserHero.tsx @@ -1,6 +1,17 @@ -import React from 'react'; -import { Avatar, Box, Icon, Icons, Text } from 'folds'; +import React, { useState } from 'react'; +import { + Avatar, + Box, + Icon, + Icons, + Modal, + Overlay, + OverlayBackdrop, + OverlayCenter, + Text, +} from 'folds'; import classNames from 'classnames'; +import FocusTrap from 'focus-trap-react'; import * as css from './styles.css'; import { UserAvatar } from '../user-avatar'; import colorMXID from '../../../util/colorMXID'; @@ -8,6 +19,8 @@ import { getMxIdLocalPart } from '../../utils/matrix'; import { BreakWord, LineClamp3 } from '../../styles/Text.css'; import { UserPresence } from '../../hooks/useUserPresence'; import { AvatarPresence, PresenceBadge } from '../presence'; +import { ImageViewer } from '../image-viewer'; +import { stopPropagation } from '../../utils/keyboard'; type UserHeroProps = { userId: string; @@ -15,6 +28,8 @@ type UserHeroProps = { presence?: UserPresence; }; export function UserHero({ userId, avatarUrl, presence }: UserHeroProps) { + const [viewAvatar, setViewAvatar] = useState(); + return (
- {avatarUrl && {userId}} + {avatarUrl && ( + {userId} + )}
} > - + setViewAvatar(avatarUrl) : undefined} + className={css.UserHeroAvatar} + size="500" + > + {viewAvatar && ( + }> + + setViewAvatar(undefined), + clickOutsideDeactivates: true, + escapeDeactivates: stopPropagation, + }} + > + evt.stopPropagation()}> + setViewAvatar(undefined)} + /> + + + + + )}
); diff --git a/src/app/components/user-profile/styles.css.ts b/src/app/components/user-profile/styles.css.ts index ad6d5a95..62272a2e 100644 --- a/src/app/components/user-profile/styles.css.ts +++ b/src/app/components/user-profile/styles.css.ts @@ -39,4 +39,16 @@ export const UserAvatarContainer = style({ }); export const UserHeroAvatar = style({ outline: `${config.borderWidth.B600} solid ${color.Surface.Container}`, + selectors: { + 'button&': { + cursor: 'pointer', + }, + }, +}); +export const UserHeroAvatarImg = style({ + selectors: { + [`button${UserHeroAvatar}:hover &`]: { + filter: 'brightness(0.5)', + }, + }, });