From e8865cec5f9329dafc344ac676fcdd43fc7530b6 Mon Sep 17 00:00:00 2001 From: heaven Date: Wed, 6 May 2026 16:19:34 +0300 Subject: [PATCH] fix(direct): lock DmStreamRow title-block height so the room name stops jumping when row 2 collapses on hover --- src/app/features/room-nav/DmStreamRow.tsx | 53 +++++---------------- src/app/features/room-nav/styles.css.ts | 56 ++++++++++++++++++++++- 2 files changed, 67 insertions(+), 42 deletions(-) diff --git a/src/app/features/room-nav/DmStreamRow.tsx b/src/app/features/room-nav/DmStreamRow.tsx index 9eecec8c..b3b79efc 100644 --- a/src/app/features/room-nav/DmStreamRow.tsx +++ b/src/app/features/room-nav/DmStreamRow.tsx @@ -15,7 +15,6 @@ import { RectCords, Spinner, Text, - color, config, toRem, } from 'folds'; @@ -62,9 +61,7 @@ import { useCallPreferencesAtom } from '../../state/hooks/callPreferences'; import { useAutoDiscoveryInfo } from '../../hooks/useAutoDiscoveryInfo'; import { livekitSupport } from '../../hooks/useLivekitSupport'; import { timeHourMinute } from '../../utils/time'; - -const MONO_FONT = '"JetBrains Mono Variable", ui-monospace, monospace'; -const ROW_MIN_HEIGHT = toRem(68); +import * as css from './styles.css'; type DmStreamRowMenuProps = { room: Room; @@ -346,7 +343,7 @@ export function DmStreamRow({ room, selected, notificationMode, linkPath }: DmSt aria-selected={selected} data-hover={!!menuAnchor} onContextMenu={handleContextMenu} - style={{ minHeight: ROW_MIN_HEIGHT, boxSizing: 'border-box' }} + className={css.DmRowOuter} {...hoverProps} {...focusWithinProps} > @@ -357,11 +354,7 @@ export function DmStreamRow({ room, selected, notificationMode, linkPath }: DmSt grow="Yes" alignItems="Center" gap="300" - style={{ - minHeight: ROW_MIN_HEIGHT, - boxSizing: 'border-box', - padding: `${toRem(8)} 0`, - }} + className={css.DmRowInner} > - - + + {roomName} {timeLabel && !optionsVisible && ( - - {timeLabel} - + {timeLabel} )} - - + + {typingMember.length > 0 ? ( - - - + ) : ( {previewText} diff --git a/src/app/features/room-nav/styles.css.ts b/src/app/features/room-nav/styles.css.ts index b5701a6f..77fa0115 100644 --- a/src/app/features/room-nav/styles.css.ts +++ b/src/app/features/room-nav/styles.css.ts @@ -1,5 +1,5 @@ import { style } from '@vanilla-extract/css'; -import { config } from 'folds'; +import { color, config, toRem } from 'folds'; export const CategoryButton = style({ flexGrow: 1, @@ -7,3 +7,57 @@ export const CategoryButton = style({ export const CategoryButtonIcon = style({ opacity: config.opacity.P400, }); + +const DmRowMinHeight = toRem(68); +const DmRowTitleBlockHeight = toRem(40); + +export const DmRowOuter = style({ + minHeight: DmRowMinHeight, + boxSizing: 'border-box', +}); + +export const DmRowInner = style({ + minHeight: DmRowMinHeight, + boxSizing: 'border-box', + padding: `${toRem(8)} 0`, +}); + +// Locks the title block to its natural 2-line height so the name does +// not jump vertically when the second row's content (preview / unread +// badge / notification icon) collapses to 0px on hover. Bridged rooms +// with no m.room.message yet but a synced unread badge are the obvious +// trigger; the same pathology applies to any (empty preview + has unread) +// pair, so the fix is room-class-agnostic. +export const DmRowText = style({ + minWidth: 0, + overflow: 'hidden', + minHeight: DmRowTitleBlockHeight, +}); + +export const DmRowTextStretch = style({ + minWidth: 0, + overflow: 'hidden', +}); + +export const DmRowName = style({ + fontWeight: 600, +}); + +export const DmRowTime = style({ + fontFamily: '"JetBrains Mono Variable", ui-monospace, monospace', + fontSize: toRem(10.5), + color: color.Surface.OnContainer, + opacity: 0.55, + fontVariantNumeric: 'tabular-nums', + flexShrink: 0, + whiteSpace: 'nowrap', +}); + +export const DmRowPreview = style({ + opacity: 0.6, +}); + +export const DmRowPreviewUnread = style({ + opacity: 0.85, + fontWeight: 500, +});