From 997d98c65c14073846cfe7b2168075193f887375 Mon Sep 17 00:00:00 2001 From: Hampus Date: Mon, 28 Sep 2026 18:47:42 +0200 Subject: [PATCH] fix(app): fade messages behind the composer status row (#3020) --- fluxer_app/scripts/GenerateThemeVariables.ts | 4 --- .../components/ChannelMessages.module.css | 32 +++++++++++++++++++ .../channel/components/ChannelMessages.tsx | 11 +++++++ .../components/SlowmodeIndicator.module.css | 6 ++-- .../channel/components/SlowmodeIndicator.tsx | 6 ++-- .../textarea/InputWrapper.module.css | 26 +-------------- 6 files changed, 50 insertions(+), 35 deletions(-) diff --git a/fluxer_app/scripts/GenerateThemeVariables.ts b/fluxer_app/scripts/GenerateThemeVariables.ts index 7e97aec72..2541e0d8f 100644 --- a/fluxer_app/scripts/GenerateThemeVariables.ts +++ b/fluxer_app/scripts/GenerateThemeVariables.ts @@ -557,10 +557,6 @@ const SKELETON_SURFACE_INVARIANTS: ReadonlyArray = [ file: 'src/features/channel/components/MemberListSkeleton.tsx', counts: {'style={MEMBER_LIST_METRICS_STYLE}': 2}, }, - { - file: 'src/features/channel/components/textarea/InputWrapper.module.css', - requires: ['.composerRoot:has(.statusTypingSlot, .statusSlowmodeSlot)::before'], - }, { file: 'src/features/app/components/layout/GuildsLayout.module.css', requires: [ diff --git a/fluxer_app/src/features/channel/components/ChannelMessages.module.css b/fluxer_app/src/features/channel/components/ChannelMessages.module.css index 40a4dbf22..99aced3f6 100644 --- a/fluxer_app/src/features/channel/components/ChannelMessages.module.css +++ b/fluxer_app/src/features/channel/components/ChannelMessages.module.css @@ -14,6 +14,8 @@ } .scrollerContainer { + --scroller-track-block-end-inset: var(--composer-status-safe-area, 0px); + --messages-bottom-fade-fill: var(--composer-surface-color, var(--background-secondary-lighter)); position: absolute; inset: 0; display: flex; @@ -24,6 +26,36 @@ width: 100%; } +.bottomFade { + position: absolute; + inset-block-end: 0; + inset-inline: 0 1rem; + z-index: 1; + height: 1rem; + background: linear-gradient(to bottom, transparent, var(--messages-bottom-fade-fill)); + pointer-events: none; +} + +.bottomFadeStatusAtBottom { + height: var(--composer-status-safe-area); + background: linear-gradient( + to bottom, + transparent, + var(--messages-bottom-fade-fill) var(--composer-status-safe-gap), + var(--messages-bottom-fade-fill) 100% + ); +} + +.bottomFadeStatusScrolled { + height: calc(var(--composer-status-safe-area) + 4rem); + background: linear-gradient( + to bottom, + transparent, + var(--messages-bottom-fade-fill) calc(4rem + var(--composer-status-safe-gap)), + var(--messages-bottom-fade-fill) 100% + ); +} + .scrollerContent { display: flex; flex-direction: column; diff --git a/fluxer_app/src/features/channel/components/ChannelMessages.tsx b/fluxer_app/src/features/channel/components/ChannelMessages.tsx index 280e27530..b0f1c64dd 100644 --- a/fluxer_app/src/features/channel/components/ChannelMessages.tsx +++ b/fluxer_app/src/features/channel/components/ChannelMessages.tsx @@ -14,6 +14,7 @@ import styles from '@app/features/channel/components/ChannelMessages.module.css' import {ChannelWelcomeSection} from '@app/features/channel/components/ChannelWelcomeSection'; import {CollapsedMessageVisibilityProvider} from '@app/features/channel/components/CollapsedMessageVisibilityContext'; import {NewMessagesBar} from '@app/features/channel/components/NewMessagesBar'; +import {usePresentableTypingUsers} from '@app/features/channel/components/TypingUsers'; import {UploadManager} from '@app/features/channel/components/UploadManager'; import type {Channel} from '@app/features/channel/models/Channel'; import GatewayConnection from '@app/features/gateway/transport/GatewayConnection'; @@ -637,6 +638,7 @@ export const Messages = observer(function Messages({ ? i18n._(MESSAGE_LIST_FOR_DESCRIPTOR, {channelName: channel.name}) : i18n._(MESSAGE_LIST_DESCRIPTOR); const messageListLiveMode = Accessibility.screenReaderAnnounceNewMessages && state.isAtBottom ? 'polite' : 'off'; + const composerStatusVisible = usePresentableTypingUsers(channel).length > 0 || channel.rateLimitPerUser > 0; const topFillerVisible = selectChannelMessagesFillerVisible({ reducedMotion: Accessibility.useReducedMotion, scrollManagerInitialized: scrollManager.lifecycleIsInitialized(), @@ -719,6 +721,15 @@ export const Messages = observer(function Messages({ + {bottomBar} diff --git a/fluxer_app/src/features/channel/components/SlowmodeIndicator.module.css b/fluxer_app/src/features/channel/components/SlowmodeIndicator.module.css index b25a0c1f3..8dec3ec87 100644 --- a/fluxer_app/src/features/channel/components/SlowmodeIndicator.module.css +++ b/fluxer_app/src/features/channel/components/SlowmodeIndicator.module.css @@ -3,7 +3,7 @@ .container { display: flex; align-items: center; - gap: 0.1875rem; + gap: 0.25rem; height: var(--slowmode-indicator-height, 1.125rem); max-width: 100%; min-width: 0; @@ -22,9 +22,9 @@ overflow: hidden; text-overflow: ellipsis; white-space: nowrap; - font-weight: 600; + font-weight: 500; font-size: 0.75rem; - line-height: 1; + line-height: 1rem; font-variant-numeric: tabular-nums; } diff --git a/fluxer_app/src/features/channel/components/SlowmodeIndicator.tsx b/fluxer_app/src/features/channel/components/SlowmodeIndicator.tsx index 86f41bc98..cf31135db 100644 --- a/fluxer_app/src/features/channel/components/SlowmodeIndicator.tsx +++ b/fluxer_app/src/features/channel/components/SlowmodeIndicator.tsx @@ -115,15 +115,15 @@ export const SlowmodeIndicator = observer(({slowmodeRemaining, slowmodeDuration, className={clsx(styles.container, onCooldown && styles.cooldown)} data-flx="channel.slowmode-indicator.container" > - - {statusLabel} - + + {statusLabel} + ); diff --git a/fluxer_app/src/features/channel/components/textarea/InputWrapper.module.css b/fluxer_app/src/features/channel/components/textarea/InputWrapper.module.css index bbfd8251c..98aade9ff 100644 --- a/fluxer_app/src/features/channel/components/textarea/InputWrapper.module.css +++ b/fluxer_app/src/features/channel/components/textarea/InputWrapper.module.css @@ -48,28 +48,6 @@ --composer-surface-fill: var(--composer-surface-color, var(--background-secondary-lighter)); } -.composerRoot:has(.statusTypingSlot, .statusSlowmodeSlot)::before { - content: ''; - position: absolute; - bottom: 100%; - inset-inline: calc(-1 * var(--composer-box-inset-inline, 0px)); - height: var(--composer-status-safe-area); - background: - radial-gradient(farthest-side at 0% 100%, var(--composer-surface-fill) 55%, transparent 100%) left bottom / - min(28rem, 70%) 160% no-repeat, - radial-gradient(farthest-side at 100% 100%, var(--composer-surface-fill) 55%, transparent 100%) right bottom / - min(18rem, 50%) 160% no-repeat, - linear-gradient( - to bottom, - transparent 0%, - color-mix(in srgb, var(--composer-surface-fill) 64%, transparent) 20%, - color-mix(in srgb, var(--composer-surface-fill) 92%, transparent) 40%, - var(--composer-surface-fill) 60%, - var(--composer-surface-fill) 100% - ); - pointer-events: none; -} - .statusRail { --typing-pill-height: var(--composer-status-line-height, 1.125rem); --slowmode-indicator-height: var(--composer-status-line-height, 1.125rem); @@ -85,9 +63,6 @@ max-width: 100%; height: var(--composer-status-line-height, 1.125rem); box-sizing: border-box; - text-shadow: - 0 0 0.1875rem var(--composer-surface-fill), - 0 0 0.5rem var(--composer-surface-fill); pointer-events: none; } @@ -117,6 +92,7 @@ min-width: 0; max-width: min(14rem, 35vw); justify-self: end; + padding-inline-end: max(0px, calc(1rem - var(--composer-box-padding-inline, 0px))); pointer-events: auto; }