From 18a8a48e09e170dcee4207c4f81933c68a097cf7 Mon Sep 17 00:00:00 2001 From: Oliver Lazoroski Date: Tue, 10 Mar 2026 16:02:33 +0100 Subject: [PATCH 1/3] fix: keep mobile sidebar overlays from shifting content --- .../ChannelList/styling/ChannelList.scss | 84 +++++++++++++++++-- .../styling/ChannelListHeader.scss | 27 ++++-- src/components/ChatView/styling/ChatView.scss | 13 +++ .../ThreadList/styling/ThreadList.scss | 9 +- 4 files changed, 115 insertions(+), 18 deletions(-) diff --git a/src/components/ChannelList/styling/ChannelList.scss b/src/components/ChannelList/styling/ChannelList.scss index 51621d8f6..96cd55720 100644 --- a/src/components/ChannelList/styling/ChannelList.scss +++ b/src/components/ChannelList/styling/ChannelList.scss @@ -13,6 +13,21 @@ /* Box shadow applied to the component */ --str-chat__channel-list-box-shadow: none; + /* Animation duration used when the component enters or exits */ + --str-chat__channel-list-transition-duration: 180ms; + + /* Animation easing used when the component enters or exits */ + --str-chat__channel-list-transition-easing: ease; + + /* Horizontal offset used by the sidebar enter/exit transition */ + --str-chat__channel-list-transition-offset: 8px; + + /* Default desktop width of the channel list. Override to match custom layouts. */ + --str-chat__channel-list-width: 30%; + + /* Default mobile overlay width of the channel list. Override to match custom layouts. */ + --str-chat__channel-list-mobile-width: 100%; + /* Top border of the component */ --str-chat__channel-list-border-block-start: none; @@ -84,8 +99,27 @@ .str-chat__channel-list { display: flex; + flex: 0 0 var(--str-chat__channel-list-width); flex-direction: column; height: 100%; + max-width: 100%; + min-width: 280px; + opacity: 1; + transform: translateX(0); + transition: + flex-basis var(--str-chat__channel-list-transition-duration) + var(--str-chat__channel-list-transition-easing), + min-width var(--str-chat__channel-list-transition-duration) + var(--str-chat__channel-list-transition-easing), + width var(--str-chat__channel-list-transition-duration) + var(--str-chat__channel-list-transition-easing), + max-width var(--str-chat__channel-list-transition-duration) + var(--str-chat__channel-list-transition-easing), + opacity var(--str-chat__channel-list-transition-duration) + var(--str-chat__channel-list-transition-easing), + transform var(--str-chat__channel-list-transition-duration) + var(--str-chat__channel-list-transition-easing); + width: var(--str-chat__channel-list-width); @include utils.scrollable-y; @include utils.component-layer-overrides('channel-list'); @@ -141,28 +175,60 @@ /* Mobile: hide when nav closed; when open show as overlay. */ @media (max-width: 767px) { - display: none; + box-shadow: var(--str-chat__channel-list-box-shadow); + flex-basis: auto; + inset-inline-start: 0; + max-width: 100%; + min-width: 0; + opacity: 0; + pointer-events: none; + position: absolute; + top: 0; + bottom: 0; + transform: translateX(calc(0px - var(--str-chat__channel-list-transition-offset))); + visibility: hidden; + width: var(--str-chat__channel-list-mobile-width); + z-index: 1; + transition: none; + + .str-chat__chat-view & { + inset-inline-start: var(--str-chat__chat-view-selector-mobile-width, 0px); + width: calc(100% - var(--str-chat__chat-view-selector-mobile-width, 0px)); + } &.str-chat__channel-list--open { - display: flex; - position: absolute; - top: 0; - bottom: 0; - z-index: 1; - min-width: 280px; - max-width: 100%; - box-shadow: var(--str-chat__channel-list-box-shadow); + opacity: 1; + pointer-events: auto; + transform: translateX(0); + visibility: visible; } } /* Desktop (≥768px): collapse when nav closed so main content uses space. */ @media (min-width: 768px) { + &.str-chat__channel-list--open { + flex-basis: var(--str-chat__channel-list-width); + max-width: 100%; + min-width: 280px; + opacity: 1; + pointer-events: auto; + transform: translateX(0); + width: var(--str-chat__channel-list-width); + } + &:not(.str-chat__channel-list--open) { flex: 0 0 0; width: 0; min-width: 0; max-width: 0; + opacity: 0; overflow: hidden; + pointer-events: none; + transform: translateX(calc(0px - var(--str-chat__channel-list-transition-offset))); } } + + @media (prefers-reduced-motion: reduce) { + transition: none; + } } diff --git a/src/components/ChannelList/styling/ChannelListHeader.scss b/src/components/ChannelList/styling/ChannelListHeader.scss index 4e099e6a0..81f139526 100644 --- a/src/components/ChannelList/styling/ChannelListHeader.scss +++ b/src/components/ChannelList/styling/ChannelListHeader.scss @@ -1,8 +1,14 @@ .str-chat__channel-list__header { display: flex; align-items: center; + opacity: 1; padding: var(--spacing-md); - // height: var(--str-chat__channel-header-height); + transform: translateX(0); + transition: + opacity var(--str-chat__channel-list-transition-duration, 180ms) + var(--str-chat__channel-list-transition-easing, ease), + transform var(--str-chat__channel-list-transition-duration, 180ms) + var(--str-chat__channel-list-transition-easing, ease); width: 100%; .str-chat__channel-list__header__title { @@ -12,11 +18,18 @@ } &.str-chat__channel-list__header--sidebar-collapsed { - flex: 0 0 0; - width: 0; - min-width: 0; - max-width: 0; - overflow: hidden; - padding: 0; + opacity: 0; + pointer-events: none; + transform: translateX( + calc(0px - var(--str-chat__channel-list-transition-offset, 8px)) + ); + } + + @media (max-width: 767px) { + transition: none; + } + + @media (prefers-reduced-motion: reduce) { + transition: none; } } diff --git a/src/components/ChatView/styling/ChatView.scss b/src/components/ChatView/styling/ChatView.scss index 634e9f998..4a1978e2f 100644 --- a/src/components/ChatView/styling/ChatView.scss +++ b/src/components/ChatView/styling/ChatView.scss @@ -1,6 +1,9 @@ .str-chat { --str-chat-selector-background-color: var(--str-chat__secondary-background-color); --str-chat-selector-border-color: var(--border-core-subtle); + --str-chat__chat-view-selector-mobile-width: calc( + var(--spacing-md) + var(--spacing-md) + var(--spacing-xs) + var(--spacing-xs) + 20px + ); --str-chat-selector-button-color-default: var(--str-chat__text-low-emphasis-color); --str-chat-selector-button-color-selected: var(--str-chat__text-color); @@ -12,6 +15,7 @@ display: flex; width: 100%; height: 100%; + position: relative; .str-chat__chat-view__selector { display: flex; @@ -29,6 +33,11 @@ &.str-chat__chat-view__selector--nav-open { display: flex; + inset-block: 0; + inset-inline-start: 0; + position: absolute; + width: var(--str-chat__chat-view-selector-mobile-width); + z-index: 2; } } @@ -111,10 +120,14 @@ .str-chat__chat-view__channels { display: flex; flex-grow: 1; + min-width: 0; + position: relative; } .str-chat__chat-view__threads { display: flex; flex-grow: 1; + min-width: 0; + position: relative; } } diff --git a/src/components/Threads/ThreadList/styling/ThreadList.scss b/src/components/Threads/ThreadList/styling/ThreadList.scss index df6d46370..c2d8c0ab6 100644 --- a/src/components/Threads/ThreadList/styling/ThreadList.scss +++ b/src/components/Threads/ThreadList/styling/ThreadList.scss @@ -23,13 +23,18 @@ &.str-chat__thread-list-container--open { display: flex; + inset-inline-start: 0; position: absolute; top: 0; bottom: 0; + width: 100%; z-index: 1; - min-width: 280px; - max-width: 100%; box-shadow: var(--str-chat__thread-list-box-shadow); + + .str-chat__chat-view & { + inset-inline-start: var(--str-chat__chat-view-selector-mobile-width, 0px); + width: calc(100% - var(--str-chat__chat-view-selector-mobile-width, 0px)); + } } } From d7e1c2aa0649de7a304220517279da2a024a044e Mon Sep 17 00:00:00 2001 From: Oliver Lazoroski Date: Tue, 10 Mar 2026 16:16:25 +0100 Subject: [PATCH 2/3] docs: update AGENTS guidance --- AGENTS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/AGENTS.md b/AGENTS.md index 7704f50ea..a3c685ac0 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -72,6 +72,7 @@ yarn lint-fix #### Commit / PR conventions - Never commit directly to main, always create a feature branch. +- Never commit unless explicitly requested. - Keep PRs small and focused; include tests. - Follow the project’s “zero warnings” policy—fix new warnings and avoid introducing any. - For UI changes, attach comparison screenshots (before/after) where feasible. From 59eaec033fc3b7f58891b8f265f1c0a12d214ee2 Mon Sep 17 00:00:00 2001 From: Oliver Lazoroski Date: Tue, 10 Mar 2026 16:16:40 +0100 Subject: [PATCH 3/3] fix: use slide-only mobile sidebar overlays --- .../ChannelList/styling/ChannelList.scss | 8 +++-- .../styling/ChannelListHeader.scss | 5 ++++ src/components/ChatView/styling/ChatView.scss | 29 ++++++++++++++----- .../ThreadList/styling/ThreadList.scss | 27 ++++++++++++----- .../ThreadList/styling/ThreadListHeader.scss | 29 +++++++++++++++---- 5 files changed, 74 insertions(+), 24 deletions(-) diff --git a/src/components/ChannelList/styling/ChannelList.scss b/src/components/ChannelList/styling/ChannelList.scss index 96cd55720..72751173c 100644 --- a/src/components/ChannelList/styling/ChannelList.scss +++ b/src/components/ChannelList/styling/ChannelList.scss @@ -180,7 +180,6 @@ inset-inline-start: 0; max-width: 100%; min-width: 0; - opacity: 0; pointer-events: none; position: absolute; top: 0; @@ -189,7 +188,10 @@ visibility: hidden; width: var(--str-chat__channel-list-mobile-width); z-index: 1; - transition: none; + transition: + transform var(--str-chat__channel-list-transition-duration) + var(--str-chat__channel-list-transition-easing), + visibility 0s linear var(--str-chat__channel-list-transition-duration); .str-chat__chat-view & { inset-inline-start: var(--str-chat__chat-view-selector-mobile-width, 0px); @@ -197,9 +199,9 @@ } &.str-chat__channel-list--open { - opacity: 1; pointer-events: auto; transform: translateX(0); + transition-delay: 0s, 0s; visibility: visible; } } diff --git a/src/components/ChannelList/styling/ChannelListHeader.scss b/src/components/ChannelList/styling/ChannelListHeader.scss index 81f139526..734d1d9ac 100644 --- a/src/components/ChannelList/styling/ChannelListHeader.scss +++ b/src/components/ChannelList/styling/ChannelListHeader.scss @@ -27,6 +27,11 @@ @media (max-width: 767px) { transition: none; + + &.str-chat__channel-list__header--sidebar-collapsed { + opacity: 1; + transform: none; + } } @media (prefers-reduced-motion: reduce) { diff --git a/src/components/ChatView/styling/ChatView.scss b/src/components/ChatView/styling/ChatView.scss index 4a1978e2f..4afef9cdd 100644 --- a/src/components/ChatView/styling/ChatView.scss +++ b/src/components/ChatView/styling/ChatView.scss @@ -1,6 +1,9 @@ .str-chat { --str-chat-selector-background-color: var(--str-chat__secondary-background-color); --str-chat-selector-border-color: var(--border-core-subtle); + --str-chat__chat-view-selector-transition-duration: 180ms; + --str-chat__chat-view-selector-transition-easing: ease; + --str-chat__chat-view-selector-transition-offset: 8px; --str-chat__chat-view-selector-mobile-width: calc( var(--spacing-md) + var(--spacing-md) + var(--spacing-xs) + var(--spacing-xs) + 20px ); @@ -28,16 +31,28 @@ /* Mobile: hide when nav closed, show when nav open. */ @media (max-width: 767px) { &.str-chat__chat-view__selector--nav-closed { - display: none; + pointer-events: none; + transform: translateX( + calc(0px - var(--str-chat__chat-view-selector-transition-offset)) + ); + visibility: hidden; } + inset-block: 0; + inset-inline-start: 0; + position: absolute; + transition: + transform var(--str-chat__chat-view-selector-transition-duration) + var(--str-chat__chat-view-selector-transition-easing), + visibility 0s linear var(--str-chat__chat-view-selector-transition-duration); + width: var(--str-chat__chat-view-selector-mobile-width); + z-index: 2; + &.str-chat__chat-view__selector--nav-open { - display: flex; - inset-block: 0; - inset-inline-start: 0; - position: absolute; - width: var(--str-chat__chat-view-selector-mobile-width); - z-index: 2; + pointer-events: auto; + transform: translateX(0); + transition-delay: 0s, 0s; + visibility: visible; } } diff --git a/src/components/Threads/ThreadList/styling/ThreadList.scss b/src/components/Threads/ThreadList/styling/ThreadList.scss index c2d8c0ab6..8648c56b6 100644 --- a/src/components/Threads/ThreadList/styling/ThreadList.scss +++ b/src/components/Threads/ThreadList/styling/ThreadList.scss @@ -19,17 +19,28 @@ /* Mobile: hide when nav closed; when open show as overlay. */ @media (max-width: 767px) { - display: none; + inset-inline-start: 0; + pointer-events: none; + position: absolute; + top: 0; + bottom: 0; + transform: translateX( + calc(0px - var(--str-chat__channel-list-transition-offset, 8px)) + ); + transition: + transform var(--str-chat__channel-list-transition-duration, 180ms) + var(--str-chat__channel-list-transition-easing, ease), + visibility 0s linear var(--str-chat__channel-list-transition-duration, 180ms); + visibility: hidden; + width: 100%; + z-index: 1; &.str-chat__thread-list-container--open { - display: flex; - inset-inline-start: 0; - position: absolute; - top: 0; - bottom: 0; - width: 100%; - z-index: 1; box-shadow: var(--str-chat__thread-list-box-shadow); + pointer-events: auto; + transform: translateX(0); + transition-delay: 0s, 0s; + visibility: visible; .str-chat__chat-view & { inset-inline-start: var(--str-chat__chat-view-selector-mobile-width, 0px); diff --git a/src/components/Threads/ThreadList/styling/ThreadListHeader.scss b/src/components/Threads/ThreadList/styling/ThreadListHeader.scss index cbbb6b5af..096407ae1 100644 --- a/src/components/Threads/ThreadList/styling/ThreadListHeader.scss +++ b/src/components/Threads/ThreadList/styling/ThreadListHeader.scss @@ -1,8 +1,15 @@ .str-chat__thread-list__header { display: flex; align-items: center; + opacity: 1; padding: var(--spacing-md); height: var(--str-chat__channel-header-height); + transform: translateX(0); + transition: + opacity var(--str-chat__channel-list-transition-duration, 180ms) + var(--str-chat__channel-list-transition-easing, ease), + transform var(--str-chat__channel-list-transition-duration, 180ms) + var(--str-chat__channel-list-transition-easing, ease); width: 100%; .str-chat__thread-list__header__title { @@ -12,15 +19,25 @@ } &.str-chat__thread-list__header--sidebar-collapsed { - flex: 0 0 0; - width: 0; - min-width: 0; - max-width: 0; - overflow: hidden; - padding: 0; + opacity: 0; + pointer-events: none; + transform: translateX(calc(0px - var(--str-chat__channel-list-transition-offset, 8px))); .str-chat__header-sidebar-toggle { // Compact styling when sidebar collapsed } } + + @media (max-width: 767px) { + transition: none; + + &.str-chat__thread-list__header--sidebar-collapsed { + opacity: 1; + transform: none; + } + } + + @media (prefers-reduced-motion: reduce) { + transition: none; + } }