From 2174f55b873ba6e0da3f71108295896faa23edf7 Mon Sep 17 00:00:00 2001 From: Karl Stolley Date: Wed, 13 Aug 2025 14:43:35 -0500 Subject: [PATCH] left_sidebar: Correct unread-pulse on collapsed views. --- web/styles/app_variables.css | 3 +++ web/styles/left_sidebar.css | 19 +++++++++++++++++-- web/styles/zulip.css | 10 +++++++--- 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/web/styles/app_variables.css b/web/styles/app_variables.css index b97681b5bf..c30129087d 100644 --- a/web/styles/app_variables.css +++ b/web/styles/app_variables.css @@ -384,6 +384,9 @@ /* Legacy values */ --legacy-body-line-height-unitless: calc(20 / 14); + /* Special effects */ + --pulse-unread-scale-max: 1.5; + /* Message area */ /* In the legacy layout at 16px/1em density, 918.6px is the widest the message area gets, so we preserve this diff --git a/web/styles/left_sidebar.css b/web/styles/left_sidebar.css index 474a4abe53..5608e53fed 100644 --- a/web/styles/left_sidebar.css +++ b/web/styles/left_sidebar.css @@ -1076,8 +1076,23 @@ li.active-sub-filter { the icon width (15px/2) plus 2px. This keeps the unread dot in correct proximity to the view icon, no matter how the row flexes or what information- - density values a user has set. 9.5px at 12px/1em. */ - transform: translateX(0.7917em); + density values a user has set. 9.5px at 12px/1em. + + We set this and its scaled counterpart as variables + for use in the pulse-unread animation to maintain the + dot's correct position relative to the view icon. */ + --unread-dot-x-offset: 0.7917em; + /* To make sure the unread dot appears to scale from the + offset dot's center in collapsed Views, we need to + adjust the translateX offset by the same amount we + scale. calc() does not play nicely with animations, + so it's critical that we calculate this value here, + well before its needed. */ + --unread-dot-x-offset-scaled: calc( + var(--unread-dot-x-offset) / var(--pulse-unread-scale-max) + ); + + transform: translateX(var(--unread-dot-x-offset)); width: 0.5em; height: 0.5em; padding: 0; diff --git a/web/styles/zulip.css b/web/styles/zulip.css index 16171cbf92..c9d0724317 100644 --- a/web/styles/zulip.css +++ b/web/styles/zulip.css @@ -844,16 +844,20 @@ strong { } @keyframes pulse-unread { + /* Only unread dots in collapsed Views + have offset variables set; all others + will fall back to 0 (no offset). */ 0% { - transform: scale(1); + transform: scale(1) translateX(var(--unread-dot-x-offset, 0)); } 50% { - transform: scale(1.5); + transform: scale(var(--pulse-unread-scale-max)) + translateX(var(--unread-dot-x-offset-scaled, 0)); } 100% { - transform: scale(1); + transform: scale(1) translateX(var(--unread-dot-x-offset, 0)); } }