From eab52f7b6c25d76dcada629704b9d6c17a1b0bf5 Mon Sep 17 00:00:00 2001 From: "v.lagerev" Date: Mon, 11 May 2026 14:09:07 +0300 Subject: [PATCH] feat(profile): merge 1:1 header avatar and title into single identity button so name taps open the profile sheet --- src/app/features/room/RoomViewHeaderDm.css.ts | 28 +++-- src/app/features/room/RoomViewHeaderDm.tsx | 101 ++++++++++-------- 2 files changed, 79 insertions(+), 50 deletions(-) diff --git a/src/app/features/room/RoomViewHeaderDm.css.ts b/src/app/features/room/RoomViewHeaderDm.css.ts index 660324cf..7d70264a 100644 --- a/src/app/features/room/RoomViewHeaderDm.css.ts +++ b/src/app/features/room/RoomViewHeaderDm.css.ts @@ -11,19 +11,31 @@ export const HeaderShell = style({ paddingLeft: config.space.S200, }); -// Tap-target wrapper for the peer avatar — opens the user-room-profile sheet -// in 1:1 chrome. Reset native button styling so it sits flush with the -// surrounding header row. -export const PeerAvatarTrigger = style({ +// Tap-target wrapper for the peer identity (avatar + title block) — opens +// the user-room-profile sheet in 1:1 chrome. Wrapping both the avatar and +// the title together gives one keyboard tab stop and one focus outline +// around the entire identity area, matching WhatsApp/Telegram chat-header +// behaviour where tapping the room name also opens contact info. +// +// Reset native button styling so the contents sit flush with the +// surrounding header row; the inner gap mirrors the parent row's `gap=200` +// so the avatar→title spacing is unchanged. `flex-grow: 1` + `min-width: 0` +// replaces the title Box's role of taking the remaining horizontal space +// and allowing the room name to truncate. +export const PeerIdentityTrigger = style({ background: 'transparent', border: 'none', padding: 0, cursor: 'pointer', - display: 'inline-flex', + display: 'flex', alignItems: 'center', - justifyContent: 'center', - borderRadius: '50%', - flexShrink: 0, + gap: config.space.S200, + flexGrow: 1, + minWidth: 0, + textAlign: 'left', + font: 'inherit', + color: 'inherit', + borderRadius: toRem(8), ':focus-visible': { outline: `2px solid ${color.Primary.Main}`, outlineOffset: 2, diff --git a/src/app/features/room/RoomViewHeaderDm.tsx b/src/app/features/room/RoomViewHeaderDm.tsx index a44765c6..20979211 100644 --- a/src/app/features/room/RoomViewHeaderDm.tsx +++ b/src/app/features/room/RoomViewHeaderDm.tsx @@ -572,6 +572,64 @@ export function RoomViewHeaderDm({ callView }: { callView?: boolean }) { const showHandlePart = isOneOnOne && !!handle; const showGroupSubline = !isOneOnOne; + // Title block (name row + subline) — identical for 1:1 and group; the + // difference is purely in the wrapper (clickable identity button for + // 1:1, plain row for groups). + const titleBlock = ( + +
+ + {name} + + {showOnlineTag && ( + + {t('Room.status_online')} + + )} +
+ {showHandlePart && ( + + {handle} + {e2eeChip} + + )} + {showGroupSubline && ( + + + {t('Room.members_count', { + count: memberCount, + formattedCount: memberCount, + })} + + {e2eeChip} + + )} +
+ ); + + // For 1:1 rooms wrap the avatar AND title in a single button so a tap + // anywhere on the user identity (avatar, name, handle, online tag) + // opens the user-room-profile sheet — one tab stop, one focus + // outline, single popout anchor. Groups keep the avatar non-clickable + // and the title as a plain row. + const identityArea = + isOneOnOne && peerUserId ? ( + + ) : ( + <> + {avatarNode} + {titleBlock} + + ); + return ( )} - {isOneOnOne && peerUserId ? ( - - ) : ( - {avatarNode} - )} - - -
- - {name} - - {showOnlineTag && ( - - {t('Room.status_online')} - - )} -
- {showHandlePart && ( - - {handle} - {e2eeChip} - - )} - {showGroupSubline && ( - - - {t('Room.members_count', { - count: memberCount, - formattedCount: memberCount, - })} - - {e2eeChip} - - )} -
+ {identityArea} {callButtonVisible && }