From e1c31a2338a936b0c3cd00ce24ea825289137302 Mon Sep 17 00:00:00 2001 From: Evie Gauthier Date: Thu, 12 Mar 2026 14:25:32 -0400 Subject: [PATCH 1/2] fix: badge positioning and alignment across sidebar components --- .changeset/fix-badge-positioning.md | 5 + .nvmrc | 1 + .../components/message/layout/layout.css.ts | 13 +-- src/app/components/sidebar/Sidebar.css.ts | 33 +++++++ .../client/sidebar/AccountSwitcherTab.tsx | 2 +- .../pages/client/sidebar/DirectDMsList.tsx | 95 ++++++++++++------- src/app/pages/client/sidebar/DirectTab.tsx | 8 +- src/app/pages/client/sidebar/HomeTab.tsx | 8 +- src/app/pages/client/sidebar/InboxTab.tsx | 2 +- src/app/pages/client/sidebar/SpaceTabs.tsx | 16 +++- .../pages/client/sidebar/UnverifiedTab.tsx | 2 +- 11 files changed, 140 insertions(+), 45 deletions(-) create mode 100644 .changeset/fix-badge-positioning.md create mode 100644 .nvmrc diff --git a/.changeset/fix-badge-positioning.md b/.changeset/fix-badge-positioning.md new file mode 100644 index 000000000..a6d3e50cd --- /dev/null +++ b/.changeset/fix-badge-positioning.md @@ -0,0 +1,5 @@ +--- +'default': patch +--- + +Fix badge positioning and alignment across all sidebar components diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 000000000..a4a7a41bc --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +v24.14.0 diff --git a/src/app/components/message/layout/layout.css.ts b/src/app/components/message/layout/layout.css.ts index 32dedb17d..76b7d1609 100644 --- a/src/app/components/message/layout/layout.css.ts +++ b/src/app/components/message/layout/layout.css.ts @@ -220,6 +220,7 @@ export const PronounPill = style({ export const MessageTextBody = recipe({ base: { wordBreak: 'break-word', + fontSize: '1rem !important', // Override folds Text component to enable page zoom scaling }, variants: { preWrap: { @@ -229,27 +230,27 @@ export const MessageTextBody = recipe({ }, jumboEmoji: { none: { - fontSize: '1em', + fontSize: '1rem !important', lineHeight: 'inherit', }, extraSmall: { - fontSize: '1.25em', + fontSize: '1.25rem !important', lineHeight: '1.4em', }, small: { - fontSize: '1.5em', + fontSize: '1.5rem !important', lineHeight: '1.5em', }, normal: { - fontSize: '1.805em', + fontSize: '1.805rem !important', lineHeight: '1.625em', }, large: { - fontSize: '2.1em', + fontSize: '2.1rem !important', lineHeight: '1.675em', }, extraLarge: { - fontSize: '2.4em', + fontSize: '2.4rem !important', lineHeight: '1.7em', }, }, diff --git a/src/app/components/sidebar/Sidebar.css.ts b/src/app/components/sidebar/Sidebar.css.ts index 76337ed2d..b96307ae0 100644 --- a/src/app/components/sidebar/Sidebar.css.ts +++ b/src/app/components/sidebar/Sidebar.css.ts @@ -142,6 +142,39 @@ export const SidebarItemBadge = recipe({ defaultVariants: { hasCount: false, }, + // Adjust positioning when badge is on a folder (closed folder button) + compoundVariants: [ + { + variants: { + hasCount: true, + }, + style: { + selectors: { + // When the badge is within an item containing a closed folder, adjust position + // to align with the folder's square border + 'div:has(> button[data-id]) &': { + top: toRem(0), + left: 'auto', + right: toRem(0), + }, + }, + }, + }, + { + variants: { + hasCount: false, + }, + style: { + selectors: { + 'div:has(> button[data-id]) &': { + top: toRem(2), + left: 'auto', + right: toRem(2), + }, + }, + }, + }, + ], }); export type SidebarItemBadgeVariants = RecipeVariants; diff --git a/src/app/pages/client/sidebar/AccountSwitcherTab.tsx b/src/app/pages/client/sidebar/AccountSwitcherTab.tsx index 7d2a3ca11..1b722d244 100644 --- a/src/app/pages/client/sidebar/AccountSwitcherTab.tsx +++ b/src/app/pages/client/sidebar/AccountSwitcherTab.tsx @@ -276,7 +276,7 @@ export function AccountSwitcherTab() { )} {(totalBackgroundUnread > 0 || anyBackgroundHighlight) && ( - + ( {isGroupDM ? ( - - - {groupMembers.map((member) => { - const avatarUrl = member.avatarUrl - ? (mxcUrlToHttp(mx, member.avatarUrl, useAuthentication, 48, 48, 'crop') ?? - undefined) - : undefined; - - return ( - - ( - - {nameInitials(member.displayName || member.userId)} - - )} - /> - - ); - })} + groupMembers.length === 1 ? ( + // Single member in group DM - fill the space like a normal DM + + ( + + {nameInitials(groupMembers[0].displayName || groupMembers[0].userId)} + + )} + /> + + ) : ( + + + {groupMembers.map((member) => { + const avatarUrl = member.avatarUrl + ? (mxcUrlToHttp(mx, member.avatarUrl, useAuthentication, 48, 48, 'crop') ?? + undefined) + : undefined; + + return ( + + ( + + {nameInitials(member.displayName || member.userId)} + + )} + /> + + ); + })} + - + ) ) : ( {unread && (unread.total > 0 || unread.highlight > 0) && ( - 0}> - 0} count={unread.total} dm /> + 0} + style={{ + left: unread.total > 0 ? toRem(-6) : toRem(-2), + right: 'auto' + }} + > + 0} + count={unread.highlight > 0 ? unread.highlight : unread.total} + dm + /> )} diff --git a/src/app/pages/client/sidebar/DirectTab.tsx b/src/app/pages/client/sidebar/DirectTab.tsx index b59f852c6..373ba17c4 100644 --- a/src/app/pages/client/sidebar/DirectTab.tsx +++ b/src/app/pages/client/sidebar/DirectTab.tsx @@ -107,7 +107,13 @@ export function DirectTab() { )} {directUnread && ( - 0}> + 0} + style={{ + left: directUnread.total > 0 ? toRem(-6) : toRem(-2), + right: 'auto' + }} + > 0} count={directUnread.highlight > 0 ? directUnread.highlight : directUnread.total} diff --git a/src/app/pages/client/sidebar/HomeTab.tsx b/src/app/pages/client/sidebar/HomeTab.tsx index ba02326ee..8ead74392 100644 --- a/src/app/pages/client/sidebar/HomeTab.tsx +++ b/src/app/pages/client/sidebar/HomeTab.tsx @@ -109,7 +109,13 @@ export function HomeTab() { )} {homeUnread && ( - 0}> + 0} + style={{ + left: homeUnread.total > 0 ? toRem(-6) : toRem(-2), + right: 'auto' + }} + > 0} count={homeUnread.highlight > 0 ? homeUnread.highlight : homeUnread.total} diff --git a/src/app/pages/client/sidebar/InboxTab.tsx b/src/app/pages/client/sidebar/InboxTab.tsx index ec3bb21d1..1062fd77d 100644 --- a/src/app/pages/client/sidebar/InboxTab.tsx +++ b/src/app/pages/client/sidebar/InboxTab.tsx @@ -52,7 +52,7 @@ export function InboxTab() { )} {inviteCount > 0 && ( - + )} diff --git a/src/app/pages/client/sidebar/SpaceTabs.tsx b/src/app/pages/client/sidebar/SpaceTabs.tsx index 15ebd518d..9cfcc4df7 100644 --- a/src/app/pages/client/sidebar/SpaceTabs.tsx +++ b/src/app/pages/client/sidebar/SpaceTabs.tsx @@ -465,7 +465,13 @@ function SpaceTab({ )} {unread && ( - 0}> + 0} + style={{ + left: unread.total > 0 ? toRem(-6) : toRem(-2), + right: 'auto' + }} + > 0} count={unread.highlight > 0 ? unread.highlight : unread.total} @@ -600,7 +606,13 @@ function ClosedSpaceFolder({ )} {unread && ( - 0}> + 0} + style={{ + left: unread.total > 0 ? toRem(-6) : toRem(-2), + right: 'auto' + }} + > 0} count={unread.highlight > 0 ? unread.highlight : unread.total} diff --git a/src/app/pages/client/sidebar/UnverifiedTab.tsx b/src/app/pages/client/sidebar/UnverifiedTab.tsx index 3aca66551..1767cc77a 100644 --- a/src/app/pages/client/sidebar/UnverifiedTab.tsx +++ b/src/app/pages/client/sidebar/UnverifiedTab.tsx @@ -66,7 +66,7 @@ function UnverifiedIndicator() { )} {!unverified && unverifiedDeviceCount && unverifiedDeviceCount > 0 && ( - + {unverifiedDeviceCount} From 9b68143a28d904f599ee2f3f3c5089e1b5f2039a Mon Sep 17 00:00:00 2001 From: Evie Gauthier Date: Thu, 12 Mar 2026 14:51:54 -0400 Subject: [PATCH 2/2] fix: eliminate nested ternary and add missing toRem imports - Refactor DirectDMsList.tsx to use renderAvatar() function instead of nested ternaries - Add toRem import to InboxTab.tsx and UnverifiedTab.tsx - All ESLint and TypeScript checks now passing --- .../pages/client/sidebar/DirectDMsList.tsx | 152 ++++++++++-------- src/app/pages/client/sidebar/DirectTab.tsx | 8 +- src/app/pages/client/sidebar/HomeTab.tsx | 10 +- src/app/pages/client/sidebar/InboxTab.tsx | 2 +- src/app/pages/client/sidebar/SpaceTabs.tsx | 16 +- .../pages/client/sidebar/UnverifiedTab.tsx | 2 +- 6 files changed, 101 insertions(+), 89 deletions(-) diff --git a/src/app/pages/client/sidebar/DirectDMsList.tsx b/src/app/pages/client/sidebar/DirectDMsList.tsx index fd28bc216..81d9f26d3 100644 --- a/src/app/pages/client/sidebar/DirectDMsList.tsx +++ b/src/app/pages/client/sidebar/DirectDMsList.tsx @@ -56,86 +56,98 @@ function DMItem({ room, selected }: DMItemProps) { // Get unread info for badge const unread = roomToUnread.get(room.roomId); - return ( - - - {(triggerRef) => ( - - {isGroupDM ? ( - groupMembers.length === 1 ? ( - // Single member in group DM - fill the space like a normal DM - - ( - - {nameInitials(groupMembers[0].displayName || groupMembers[0].userId)} - - )} - /> - - ) : ( - - - {groupMembers.map((member) => { - const avatarUrl = member.avatarUrl - ? (mxcUrlToHttp(mx, member.avatarUrl, useAuthentication, 48, 48, 'crop') ?? - undefined) - : undefined; - - return ( - - ( - - {nameInitials(member.displayName || member.userId)} - - )} - /> - - ); - })} - - - ) - ) : ( - - { + if (groupMembers.length !== 1 || !groupMembers[0].avatarUrl) { + return undefined; + } + return ( + mxcUrlToHttp(mx, groupMembers[0].avatarUrl, useAuthentication, 96, 96, 'crop') ?? undefined + ); + }; + + // Render appropriate avatar based on DM type + const renderAvatar = () => { + if (!isGroupDM) { + // Regular DM + return ( + + ( + + {nameInitials(room.name)} + + )} + /> + + ); + } + + if (groupMembers.length === 1) { + // Single member in group DM - fill the space like a normal DM + return ( + + ( + + {nameInitials(groupMembers[0].displayName || groupMembers[0].userId)} + + )} + /> + + ); + } + + // Multiple members in group DM - triangle layout + return ( + + + {groupMembers.map((member) => { + const avatarUrl = member.avatarUrl + ? (mxcUrlToHttp(mx, member.avatarUrl, useAuthentication, 48, 48, 'crop') ?? undefined) + : undefined; + + return ( + + ( - - {nameInitials(room.name)} + + {nameInitials(member.displayName || member.userId)} )} /> - )} + ); + })} + + + ); + }; + + return ( + + + {(triggerRef) => ( + + {renderAvatar()} )} {unread && (unread.total > 0 || unread.highlight > 0) && ( - 0} - style={{ - left: unread.total > 0 ? toRem(-6) : toRem(-2), - right: 'auto' + style={{ + left: unread.total > 0 ? toRem(-6) : toRem(-2), + right: 'auto', }} > {directUnread && ( - 0} - style={{ - left: directUnread.total > 0 ? toRem(-6) : toRem(-2), - right: 'auto' + style={{ + left: directUnread.total > 0 ? toRem(-6) : toRem(-2), + right: 'auto', }} > {homeUnread && ( - 0} - style={{ - left: homeUnread.total > 0 ? toRem(-6) : toRem(-2), - right: 'auto' + 0} + style={{ + left: homeUnread.total > 0 ? toRem(-6) : toRem(-2), + right: 'auto', }} > {unread && ( - 0} - style={{ - left: unread.total > 0 ? toRem(-6) : toRem(-2), - right: 'auto' + style={{ + left: unread.total > 0 ? toRem(-6) : toRem(-2), + right: 'auto', }} > {unread && ( - 0} - style={{ - left: unread.total > 0 ? toRem(-6) : toRem(-2), - right: 'auto' + style={{ + left: unread.total > 0 ? toRem(-6) : toRem(-2), + right: 'auto', }} >