feat(profile): merge 1:1 header avatar and title into single identity button so name taps open the profile sheet
This commit is contained in:
parent
363bd9d361
commit
eab52f7b6c
2 changed files with 79 additions and 50 deletions
|
|
@ -11,19 +11,31 @@ export const HeaderShell = style({
|
||||||
paddingLeft: config.space.S200,
|
paddingLeft: config.space.S200,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Tap-target wrapper for the peer avatar — opens the user-room-profile sheet
|
// Tap-target wrapper for the peer identity (avatar + title block) — opens
|
||||||
// in 1:1 chrome. Reset native button styling so it sits flush with the
|
// the user-room-profile sheet in 1:1 chrome. Wrapping both the avatar and
|
||||||
// surrounding header row.
|
// the title together gives one keyboard tab stop and one focus outline
|
||||||
export const PeerAvatarTrigger = style({
|
// 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',
|
background: 'transparent',
|
||||||
border: 'none',
|
border: 'none',
|
||||||
padding: 0,
|
padding: 0,
|
||||||
cursor: 'pointer',
|
cursor: 'pointer',
|
||||||
display: 'inline-flex',
|
display: 'flex',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
justifyContent: 'center',
|
gap: config.space.S200,
|
||||||
borderRadius: '50%',
|
flexGrow: 1,
|
||||||
flexShrink: 0,
|
minWidth: 0,
|
||||||
|
textAlign: 'left',
|
||||||
|
font: 'inherit',
|
||||||
|
color: 'inherit',
|
||||||
|
borderRadius: toRem(8),
|
||||||
':focus-visible': {
|
':focus-visible': {
|
||||||
outline: `2px solid ${color.Primary.Main}`,
|
outline: `2px solid ${color.Primary.Main}`,
|
||||||
outlineOffset: 2,
|
outlineOffset: 2,
|
||||||
|
|
|
||||||
|
|
@ -572,6 +572,64 @@ export function RoomViewHeaderDm({ callView }: { callView?: boolean }) {
|
||||||
const showHandlePart = isOneOnOne && !!handle;
|
const showHandlePart = isOneOnOne && !!handle;
|
||||||
const showGroupSubline = !isOneOnOne;
|
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 = (
|
||||||
|
<Box grow="Yes" direction="Column" style={{ minWidth: 0 }}>
|
||||||
|
<div className={css.TitleRow}>
|
||||||
|
<Text size={isMobile ? 'H5' : 'H4'} truncate className={css.RoomName}>
|
||||||
|
{name}
|
||||||
|
</Text>
|
||||||
|
{showOnlineTag && (
|
||||||
|
<Text as="span" size="T200" className={css.OnlineTag}>
|
||||||
|
{t('Room.status_online')}
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
{showHandlePart && (
|
||||||
|
<Text as="span" size="T200" className={css.Subline}>
|
||||||
|
<span className={css.SublineMuted}>{handle}</span>
|
||||||
|
{e2eeChip}
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
|
{showGroupSubline && (
|
||||||
|
<Text as="span" size="T200" className={css.Subline}>
|
||||||
|
<span className={css.SublineMuted}>
|
||||||
|
{t('Room.members_count', {
|
||||||
|
count: memberCount,
|
||||||
|
formattedCount: memberCount,
|
||||||
|
})}
|
||||||
|
</span>
|
||||||
|
{e2eeChip}
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
|
||||||
|
// 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 ? (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className={css.PeerIdentityTrigger}
|
||||||
|
onClick={handlePeerProfile}
|
||||||
|
aria-label={t('Room.open_profile_of', { name })}
|
||||||
|
>
|
||||||
|
{avatarNode}
|
||||||
|
{titleBlock}
|
||||||
|
</button>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<span className={css.PeerAvatarStatic}>{avatarNode}</span>
|
||||||
|
{titleBlock}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageHeader
|
<PageHeader
|
||||||
className={`${ContainerColor({ variant: 'Surface' })} ${css.HeaderShell}`}
|
className={`${ContainerColor({ variant: 'Surface' })} ${css.HeaderShell}`}
|
||||||
|
|
@ -594,48 +652,7 @@ export function RoomViewHeaderDm({ callView }: { callView?: boolean }) {
|
||||||
</BackRouteHandler>
|
</BackRouteHandler>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{isOneOnOne && peerUserId ? (
|
{identityArea}
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
className={css.PeerAvatarTrigger}
|
|
||||||
onClick={handlePeerProfile}
|
|
||||||
aria-label={t('Room.open_profile_of', { name })}
|
|
||||||
>
|
|
||||||
{avatarNode}
|
|
||||||
</button>
|
|
||||||
) : (
|
|
||||||
<span className={css.PeerAvatarStatic}>{avatarNode}</span>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<Box grow="Yes" direction="Column" style={{ minWidth: 0 }}>
|
|
||||||
<div className={css.TitleRow}>
|
|
||||||
<Text size={isMobile ? 'H5' : 'H4'} truncate className={css.RoomName}>
|
|
||||||
{name}
|
|
||||||
</Text>
|
|
||||||
{showOnlineTag && (
|
|
||||||
<Text as="span" size="T200" className={css.OnlineTag}>
|
|
||||||
{t('Room.status_online')}
|
|
||||||
</Text>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
{showHandlePart && (
|
|
||||||
<Text as="span" size="T200" className={css.Subline}>
|
|
||||||
<span className={css.SublineMuted}>{handle}</span>
|
|
||||||
{e2eeChip}
|
|
||||||
</Text>
|
|
||||||
)}
|
|
||||||
{showGroupSubline && (
|
|
||||||
<Text as="span" size="T200" className={css.Subline}>
|
|
||||||
<span className={css.SublineMuted}>
|
|
||||||
{t('Room.members_count', {
|
|
||||||
count: memberCount,
|
|
||||||
formattedCount: memberCount,
|
|
||||||
})}
|
|
||||||
</span>
|
|
||||||
{e2eeChip}
|
|
||||||
</Text>
|
|
||||||
)}
|
|
||||||
</Box>
|
|
||||||
|
|
||||||
<Box shrink="No" alignItems="Center">
|
<Box shrink="No" alignItems="Center">
|
||||||
{callButtonVisible && <DmCallButton room={room} />}
|
{callButtonVisible && <DmCallButton room={room} />}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue