Skip to content
This repository was archived by the owner on Mar 10, 2026. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions src/app/components/presence/Presence.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@

type PresenceBadgeProps = {
presence: Presence;
status?: string;

Check failure on line 25 in src/app/components/presence/Presence.tsx

View workflow job for this annotation

GitHub Actions / Lint

'status' PropType is defined but prop is never used
size?: '200' | '300' | '400' | '500';
};
export function PresenceBadge({ presence, status, size }: PresenceBadgeProps) {
export function PresenceBadge({ presence, size }: PresenceBadgeProps) {
const label = usePresenceLabel();
const badgeLabelId = useId();

Expand All @@ -39,8 +39,6 @@
<Tooltip id={badgeLabelId}>
<Box style={{ maxWidth: toRem(250) }} alignItems="Baseline" gap="100">
<Text size="L400">{label[presence]}</Text>
{status && <Text size="T200">•</Text>}
{status && <Text size="T200">{status}</Text>}
</Box>
</Tooltip>
}
Expand Down
98 changes: 53 additions & 45 deletions src/app/components/user-profile/UserHero.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,15 @@
OverlayBackdrop,
OverlayCenter,
Text,
Tooltip,
} from 'folds';
import classNames from 'classnames';
import FocusTrap from 'focus-trap-react';
import colorMXID from '$utils/colorMXID';
import { getMxIdLocalPart } from '$utils/matrix';
import { BreakWord, LineClamp3 } from '$styles/Text.css';
import { UserPresence } from '$hooks/useUserPresence';
import { stopPropagation } from '$utils/keyboard';
import { Presence, UserPresence } from '$hooks/useUserPresence';

Check failure on line 19 in src/app/components/user-profile/UserHero.tsx

View workflow job for this annotation

GitHub Actions / Lint

'Presence' is defined but never used
import { stopPropagation } from '$appUtils/keyboard';

Check failure on line 20 in src/app/components/user-profile/UserHero.tsx

View workflow job for this annotation

GitHub Actions / Lint

`$appUtils/keyboard` import should occur after import of `$components/user-avatar`

Check failure on line 20 in src/app/components/user-profile/UserHero.tsx

View workflow job for this annotation

GitHub Actions / Typecheck

Cannot find module '$appUtils/keyboard' or its corresponding type declarations.
import { useRoom } from '$hooks/useRoom';
import { useSableCosmetics } from '$hooks/useSableCosmetics';
import { useNickname } from '$hooks/useNickname';
Expand Down Expand Up @@ -58,51 +59,58 @@
/>
)}
</div>
<div className={css.UserHeroAvatarContainer}>
<AvatarPresence
className={css.UserAvatarContainer}
badge={
presence && <PresenceBadge presence={presence.presence} status={presence.status} />
}
>
<Avatar
as={avatarUrl ? 'button' : 'div'}
onClick={avatarUrl ? () => setViewAvatar(avatarUrl) : undefined}
className={css.UserHeroAvatar}
size="500"
<Box direction="Row" className={css.UserHeroAvatarStatusContainer}>
<div className={css.UserHeroAvatarContainer}>
<AvatarPresence
className={css.UserAvatarContainer}
badge={presence && <PresenceBadge presence={presence.presence} />}
>
<UserAvatar
className={css.UserHeroAvatarImg}
userId={userId}
src={avatarUrl}
alt={userId}
renderFallback={() => <Icon size="500" src={Icons.User} filled />}
/>
</Avatar>
</AvatarPresence>
{viewAvatar && (
<Overlay open backdrop={<OverlayBackdrop />}>
<OverlayCenter>
<FocusTrap
focusTrapOptions={{
initialFocus: false,
onDeactivate: () => setViewAvatar(undefined),
clickOutsideDeactivates: true,
escapeDeactivates: stopPropagation,
}}
>
<Modal size="500" onContextMenu={(evt: any) => evt.stopPropagation()}>
<ImageViewer
src={viewAvatar}
alt={userId}
requestClose={() => setViewAvatar(undefined)}
/>
</Modal>
</FocusTrap>
</OverlayCenter>
</Overlay>
<Avatar
as={avatarUrl ? 'button' : 'div'}
onClick={avatarUrl ? () => setViewAvatar(avatarUrl) : undefined}
className={css.UserHeroAvatar}
size="500"
>
<UserAvatar
className={css.UserHeroAvatarImg}
userId={userId}
src={avatarUrl}
alt={userId}
renderFallback={() => <Icon size="500" src={Icons.User} filled />}
/>
</Avatar>
</AvatarPresence>
{viewAvatar && (
<Overlay open backdrop={<OverlayBackdrop />}>
<OverlayCenter>
<FocusTrap
focusTrapOptions={{
initialFocus: false,
onDeactivate: () => setViewAvatar(undefined),
clickOutsideDeactivates: true,
escapeDeactivates: stopPropagation,
}}
>
<Modal size="500" onContextMenu={(evt: any) => evt.stopPropagation()}>
<ImageViewer
src={viewAvatar}
alt={userId}
requestClose={() => setViewAvatar(undefined)}
/>
</Modal>
</FocusTrap>
</OverlayCenter>
</Overlay>
)}
</div>
{presence?.status?.length && (
<div className={css.UserHeroStatusContainer}>
<Tooltip style={{ maxWidth: '90%', justifySelf: 'left' }}>
<Text size="T200"> {presence.status} </Text>
</Tooltip>
</div>
)}
</div>
</Box>
</Box>
);
}
Expand Down
19 changes: 15 additions & 4 deletions src/app/components/user-profile/styles.css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,18 +30,29 @@ export const UserHeroCoverFallback = style({
filter: 'blur(16px) brightness(50%)',
transform: 'scale(2)',
});

export const UserHeroAvatarContainer = style({
export const UserHeroAvatarStatusContainer = style({
position: 'relative',
height: toRem(29),
width: '100%',
});
export const UserHeroAvatarContainer = style({
position: 'relative',
paddingLeft: config.space.S400,
});
export const UserAvatarContainer = style({
position: 'absolute',
left: config.space.S400,
position: 'relative',
top: 0,
transform: 'translateY(-50%)',
backgroundColor: color.Surface.Container,
});
export const UserHeroStatusContainer = style({
position: 'relative',
transform: 'translateY(-50%)',
textAlign: 'justify',
display: 'grid',
width: '100%',
paddingLeft: '2%',
});
export const UserHeroAvatar = style({
outline: `${config.borderWidth.B600} solid ${color.Surface.Container}`,
selectors: {
Expand Down
33 changes: 24 additions & 9 deletions src/app/features/room/MembersDrawer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,11 @@
import { useFlattenPowerTagMembers, useGetMemberPowerTag } from '$hooks/useMemberPowerTag';
import { useRoomCreators } from '$hooks/useRoomCreators';
import { useSableCosmetics } from '$hooks/useSableCosmetics';
import * as css from './MembersDrawer.css';

Check failure on line 60 in src/app/features/room/MembersDrawer.tsx

View workflow job for this annotation

GitHub Actions / Lint

`./MembersDrawer.css` import should occur after import of `$hooks/useUserPresence`

import { AvatarPresence, PresenceBadge } from '$components/presence';
import { useUserPresence } from '$hooks/useUserPresence';

type MemberDrawerHeaderProps = {
room: Room;
};
Expand Down Expand Up @@ -128,6 +131,8 @@
? mx.mxcUrlToHttp(avatarMxcUrl, 100, 100, 'crop', undefined, false, useAuthentication)
: undefined;

const presence = useUserPresence(member.userId);

const { color, font } = useSableCosmetics(member.userId, room);

return (
Expand All @@ -139,14 +144,18 @@
radii="400"
onClick={onClick}
before={
<Avatar size="200">
<UserAvatar
userId={member.userId}
src={avatarUrl ?? undefined}
alt={name}
renderFallback={() => <Icon size="50" src={Icons.User} filled />}
/>
</Avatar>
<AvatarPresence
badge={presence && <PresenceBadge presence={presence.presence} size="200" />}
>
<Avatar size="200">
<UserAvatar
userId={member.userId}
src={avatarUrl ?? undefined}
alt={name}
renderFallback={() => <Icon size="50" src={Icons.User} filled />}
/>
</Avatar>
</AvatarPresence>
}
after={
typing && (
Expand All @@ -156,10 +165,16 @@
)
}
>
<Box grow="Yes">
<Box direction="Column" grow="Yes">
<Text size="T400" truncate style={{ color, fontFamily: font }}>
{name}
</Text>
{presence?.status && (
/*THE COLOR SHOULD BE BASED ON SOMETHING I CANT FIND*/

Check failure on line 173 in src/app/features/room/MembersDrawer.tsx

View workflow job for this annotation

GitHub Actions / Lint

Expected space or tab before '*/' in comment

Check failure on line 173 in src/app/features/room/MembersDrawer.tsx

View workflow job for this annotation

GitHub Actions / Lint

Expected exception block, space or tab after '/*' in comment
<Text size="T300" truncate style={{ color: '#888888', fontFamily: font }}>
{presence.status}
</Text>
)}
</Box>
</MenuItem>
);
Expand Down
Loading