Add user status emoji to member list (#34210)

* Add user status emoji to member list

* snapshots
This commit is contained in:
David Baker
2026-07-10 15:16:23 +00:00
committed by GitHub
parent f09b27db7c
commit 4518ce5c2a
5 changed files with 32 additions and 15 deletions
@@ -9,10 +9,17 @@ Please see LICENSE files in the repository root for full details.
/** Disambiguated profile needs to have a different layout in the member tile */ /** Disambiguated profile needs to have a different layout in the member tile */
.mx_MemberTileView .mx_DisambiguatedProfile { .mx_MemberTileView .mx_DisambiguatedProfile {
display: flex; /* Name and the user status emoji share the first row (with the name truncating and the emoji always visible)
flex-direction: column; Disambiguated MXID gets a full row below. */
display: grid;
grid-template-columns: min-content 1fr;
.mx_DisambiguatedProfile_userStatus {
margin-inline-start: var(--cpd-space-0-5x);
}
.mx_DisambiguatedProfile_mxid { .mx_DisambiguatedProfile_mxid {
grid-column: 1 / -1;
margin-inline-start: 0; margin-inline-start: 0;
font: var(--cpd-font-body-sm-regular); font: var(--cpd-font-body-sm-regular);
text-overflow: ellipsis; text-overflow: ellipsis;
@@ -21,7 +28,7 @@ Please see LICENSE files in the repository root for full details.
span:not(.mx_DisambiguatedProfile_mxid) { span:not(.mx_DisambiguatedProfile_mxid) {
/** /**
In a member tile, this span element is a flex child and so In a member tile, this span element is a grid child and so
we need the following for text overflow to work. we need the following for text overflow to work.
**/ **/
overflow: hidden; overflow: hidden;
@@ -18,6 +18,7 @@ import { MemberTileView } from "./common/MemberTileView";
import { InvitedIconView } from "./common/InvitedIconView"; import { InvitedIconView } from "./common/InvitedIconView";
import { type MemberWithSeparator } from "../../../../viewmodels/memberlist/MemberListViewModel"; import { type MemberWithSeparator } from "../../../../viewmodels/memberlist/MemberListViewModel";
import { DisambiguatedProfileViewModel } from "../../../../../viewmodels/room/timeline/event-tile/DisambiguatedProfileViewModel"; import { DisambiguatedProfileViewModel } from "../../../../../viewmodels/room/timeline/event-tile/DisambiguatedProfileViewModel";
import { useUserStatus } from "../../../../../hooks/useUserStatus";
interface IProps { interface IProps {
/** /**
@@ -47,17 +48,22 @@ export function RoomMemberTileView(props: IProps): JSX.Element {
/> />
); );
const name = vm.name; const name = vm.name;
const userStatus = useUserStatus(member.userId);
const disambiguatedProfileVM = useCreateAutoDisposedViewModel( const disambiguatedProfileVM = useCreateAutoDisposedViewModel(
() => () =>
new DisambiguatedProfileViewModel({ new DisambiguatedProfileViewModel({
fallbackName: name, fallbackName: name,
member, member,
withTooltip: true, withTooltip: true,
userStatus,
}), }),
); );
useEffect(() => { useEffect(() => {
disambiguatedProfileVM.setMember(name, member); disambiguatedProfileVM.setMember(name, member);
}, [disambiguatedProfileVM, member, name]); }, [disambiguatedProfileVM, member, name]);
useEffect(() => {
disambiguatedProfileVM.setUserStatus(userStatus);
}, [disambiguatedProfileVM, userStatus]);
const nameJSX = <DisambiguatedProfileView vm={disambiguatedProfileVM} className="mx_DisambiguatedProfile" />; const nameJSX = <DisambiguatedProfileView vm={disambiguatedProfileVM} className="mx_DisambiguatedProfile" />;
const presenceState = member.presenceState; const presenceState = member.presenceState;
Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

@@ -120,19 +120,23 @@ export function DisambiguatedProfileView({ vm, className }: Readonly<Disambiguat
<span className={displayNameClasses} dir="auto"> <span className={displayNameClasses} dir="auto">
{displayName} {displayName}
</span> </span>
{userStatus && (
<Tooltip description={userStatus.text}>
<Text
as="span"
size="md"
className={classNames("mx_DisambiguatedProfile_userStatus", styles.userStatus)}
>
{userStatusEmoji}
</Text>
</Tooltip>
)}
{/* mx_DisambiguatedProfile_mxid is required for PCSS selectors like .mx_MemberTileView .mx_DisambiguatedProfile_mxid */} {/* mx_DisambiguatedProfile_mxid is required for PCSS selectors like .mx_MemberTileView .mx_DisambiguatedProfile_mxid */}
{displayIdentifier && ( {displayIdentifier && (
<span className={classNames("mx_DisambiguatedProfile_mxid", styles.disambiguatedProfile_mxid)}> <span className={classNames("mx_DisambiguatedProfile_mxid", styles.disambiguatedProfile_mxid)}>
{displayIdentifier} {displayIdentifier}
</span> </span>
)} )}
{userStatus && (
<Tooltip description={userStatus.text}>
<Text as="span" size="md" className={styles.userStatus}>
{userStatusEmoji}
</Text>
</Tooltip>
)}
</div> </div>
); );
} }
@@ -31,16 +31,16 @@ exports[`DisambiguatedProfileView > renders the full example 1`] = `
> >
Eve Eve
</span> </span>
<span
class="_typography_6v6n8_153 _font-body-md-regular_6v6n8_50 mx_DisambiguatedProfile_userStatus DisambiguatedProfile-module_userStatus"
>
🏝️
</span>
<span <span
class="mx_DisambiguatedProfile_mxid DisambiguatedProfile-module_disambiguatedProfile_mxid" class="mx_DisambiguatedProfile_mxid DisambiguatedProfile-module_disambiguatedProfile_mxid"
> >
@eve:matrix.org @eve:matrix.org
</span> </span>
<span
class="_typography_6v6n8_153 _font-body-md-regular_6v6n8_50 DisambiguatedProfile-module_userStatus"
>
🏝️
</span>
</div> </div>
</div> </div>
`; `;