mirror of
https://github.com/block/buzz.git
synced 2026-08-18 06:50:31 +02:00
fix(timeline): render channel intro header flush at the top of the list
The channel intro block (the `#` avatar, channel title, "beginning of…" line, and Create agent / Add people cards) was bottom-pinned: it lived in a `min-h-full` flex column with `mt-auto`, which Slack-style pushes it to the viewport bottom when the list is short. tho wants it flush at the actual TOP of the virtualized list, since it's an in-list header — not a floating element. Gate the push-down on `topAlignIntro = showChannelIntro` and turn it off for the channel-intro case in 4 spots: the outer wrapper `min-h-full`, the SkeletonReveal `className` + `contentClassName` `min-h-full`, and the intro div's own `mt-auto`. Natural top-down flow then places the header at the top. The DM intro and the generic empty state keep their existing bottom-pin behavior. Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
This commit is contained in:
co-authored by
Taylor Ho
parent
01b292c5ef
commit
78f81e89f4
@@ -326,6 +326,13 @@ export const MessageTimeline = React.memo(function MessageTimeline({
|
|||||||
const showChannelIntro =
|
const showChannelIntro =
|
||||||
!isLoading && channelIntro !== null && directMessageIntro === null;
|
!isLoading && channelIntro !== null && directMessageIntro === null;
|
||||||
const showIntro = showDirectMessageIntro || showChannelIntro;
|
const showIntro = showDirectMessageIntro || showChannelIntro;
|
||||||
|
// The channel intro is an in-list HEADER: it must sit FLUSH at the top of the
|
||||||
|
// virtualized list (the `#` avatar / title / "beginning of…" / action cards),
|
||||||
|
// not float bottom-pinned in the viewport like the DM intro / empty state. So
|
||||||
|
// for the channel-intro case we drop the `min-h-full` fill + the intro's
|
||||||
|
// `mt-auto`, letting natural top-down flow place it at the top. Everything
|
||||||
|
// else (DM intro, generic empty) keeps the existing bottom-pin behavior.
|
||||||
|
const topAlignIntro = showChannelIntro;
|
||||||
const showGenericEmpty =
|
const showGenericEmpty =
|
||||||
!isLoading &&
|
!isLoading &&
|
||||||
deferredMessages.length === 0 &&
|
deferredMessages.length === 0 &&
|
||||||
@@ -355,7 +362,7 @@ export const MessageTimeline = React.memo(function MessageTimeline({
|
|||||||
className={cn(
|
className={cn(
|
||||||
"flex w-full flex-col gap-2",
|
"flex w-full flex-col gap-2",
|
||||||
channelChrome.contentPadding,
|
channelChrome.contentPadding,
|
||||||
(showIntro || showGenericEmpty) && "min-h-full",
|
(showIntro || showGenericEmpty) && !topAlignIntro && "min-h-full",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div ref={topSentinelRef} aria-hidden className="h-px" />
|
<div ref={topSentinelRef} aria-hidden className="h-px" />
|
||||||
@@ -369,12 +376,16 @@ export const MessageTimeline = React.memo(function MessageTimeline({
|
|||||||
<SkeletonReveal
|
<SkeletonReveal
|
||||||
className={cn(
|
className={cn(
|
||||||
"min-h-[18rem]",
|
"min-h-[18rem]",
|
||||||
(showIntro || showGenericEmpty) && "min-h-full",
|
(showIntro || showGenericEmpty) &&
|
||||||
|
!topAlignIntro &&
|
||||||
|
"min-h-full",
|
||||||
showMessageList && !showIntro && "mt-auto",
|
showMessageList && !showIntro && "mt-auto",
|
||||||
)}
|
)}
|
||||||
contentClassName={cn(
|
contentClassName={cn(
|
||||||
"flex flex-col gap-2",
|
"flex flex-col gap-2",
|
||||||
(showIntro || showGenericEmpty) && "min-h-full",
|
(showIntro || showGenericEmpty) &&
|
||||||
|
!topAlignIntro &&
|
||||||
|
"min-h-full",
|
||||||
)}
|
)}
|
||||||
loading={isLoading}
|
loading={isLoading}
|
||||||
skeleton={<TimelineSkeleton rows={timelineSkeletonRows} />}
|
skeleton={<TimelineSkeleton rows={timelineSkeletonRows} />}
|
||||||
@@ -402,7 +413,12 @@ export const MessageTimeline = React.memo(function MessageTimeline({
|
|||||||
|
|
||||||
{showChannelIntro ? (
|
{showChannelIntro ? (
|
||||||
<div
|
<div
|
||||||
className="mb-0.5 mt-auto flex w-full max-w-2xl flex-col items-start px-3 py-2 text-left"
|
className={cn(
|
||||||
|
"mb-0.5 flex w-full max-w-2xl flex-col items-start px-3 py-2 text-left",
|
||||||
|
// Channel intro is the in-list header → flush to the top, no
|
||||||
|
// bottom-pin. (mt-auto would push it to the viewport bottom.)
|
||||||
|
!topAlignIntro && "mt-auto",
|
||||||
|
)}
|
||||||
data-testid="message-channel-intro"
|
data-testid="message-channel-intro"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
|
|||||||
Reference in New Issue
Block a user