mirror of
https://github.com/block/buzz.git
synced 2026-11-11 20:01:09 +00:00
Fix typing indicator composer positioning (#512)
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -357,14 +357,6 @@ export const ChannelPane = React.memo(function ChannelPane({
|
||||
) : (
|
||||
<div className="pointer-events-none absolute inset-x-0 bottom-0 z-10">
|
||||
<div className="pointer-events-auto">
|
||||
{hasTypingActivity ? (
|
||||
<TypingIndicatorRow
|
||||
channel={activeChannel}
|
||||
currentPubkey={currentPubkey}
|
||||
profiles={profiles}
|
||||
typingPubkeys={typingPubkeys}
|
||||
/>
|
||||
) : null}
|
||||
<MessageComposer
|
||||
channelId={activeChannel?.id ?? null}
|
||||
channelName={activeChannel?.name ?? "channel"}
|
||||
@@ -395,6 +387,17 @@ export const ChannelPane = React.memo(function ChannelPane({
|
||||
}
|
||||
showTopBorder={false}
|
||||
/>
|
||||
<div className="h-6 bg-background">
|
||||
{hasTypingActivity ? (
|
||||
<TypingIndicatorRow
|
||||
channel={activeChannel}
|
||||
className="px-4 pb-1 pt-0 sm:px-6"
|
||||
currentPubkey={currentPubkey}
|
||||
profiles={profiles}
|
||||
typingPubkeys={typingPubkeys}
|
||||
/>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -544,7 +544,7 @@ export function MessageComposer({
|
||||
return (
|
||||
<footer
|
||||
className={cn(
|
||||
"relative shrink-0 bg-transparent px-4 pb-4 pt-0",
|
||||
"relative shrink-0 bg-transparent px-4 pb-2 pt-0",
|
||||
showTopBorder ? "border-t border-border/40 pt-3" : "",
|
||||
)}
|
||||
>
|
||||
@@ -554,7 +554,7 @@ export function MessageComposer({
|
||||
/>
|
||||
<div className="relative mx-auto flex w-full max-w-4xl flex-col gap-3">
|
||||
<form
|
||||
className="relative isolate rounded-2xl border border-border/50 bg-background/70 px-3 py-3 shadow-[0_4px_24px_rgba(0,0,0,0.08)] backdrop-blur-xl supports-[backdrop-filter]:bg-background/55 dark:shadow-[0_4px_24px_rgba(0,0,0,0.35)] sm:px-4"
|
||||
className="relative isolate rounded-2xl border border-border/50 bg-background/70 px-3 pb-2 pt-3 shadow-[0_4px_24px_rgba(0,0,0,0.08)] backdrop-blur-xl supports-[backdrop-filter]:bg-background/55 dark:shadow-[0_4px_24px_rgba(0,0,0,0.35)] sm:px-4"
|
||||
data-testid="message-composer"
|
||||
onDragOver={media.handleDragOver}
|
||||
onDrop={(e) => {
|
||||
|
||||
@@ -192,7 +192,7 @@ export function MessageThreadPanel({
|
||||
onScroll={syncScrollState}
|
||||
ref={threadBodyRef}
|
||||
>
|
||||
<div className="pb-8" ref={contentRef}>
|
||||
<div className="pb-10" ref={contentRef}>
|
||||
<div className="px-3 pb-1 pt-0" data-testid="message-thread-head">
|
||||
<div className="rounded-2xl">
|
||||
<MessageRow
|
||||
@@ -273,7 +273,7 @@ export function MessageThreadPanel({
|
||||
</div>
|
||||
|
||||
{!isAtBottom ? (
|
||||
<div className="pointer-events-none absolute inset-x-0 bottom-32 z-20 flex justify-center px-4">
|
||||
<div className="pointer-events-none absolute inset-x-0 bottom-36 z-20 flex justify-center px-4">
|
||||
<Button
|
||||
className="pointer-events-auto h-7 min-h-7 gap-1.5 rounded-full border-border/50 bg-background/85 px-2.5 text-[11px] font-medium text-muted-foreground shadow-sm backdrop-blur-sm hover:bg-muted/70 hover:text-foreground [&_svg]:size-3.5"
|
||||
data-testid="thread-scroll-to-latest"
|
||||
@@ -292,12 +292,6 @@ export function MessageThreadPanel({
|
||||
|
||||
<div className="pointer-events-none absolute inset-x-0 bottom-0 z-10">
|
||||
<div className="pointer-events-auto">
|
||||
<TypingIndicatorRow
|
||||
channel={channel}
|
||||
currentPubkey={currentPubkey}
|
||||
profiles={profiles}
|
||||
typingPubkeys={threadTypingPubkeys}
|
||||
/>
|
||||
<MessageComposer
|
||||
channelId={channelId}
|
||||
channelName={channelName}
|
||||
@@ -315,6 +309,17 @@ export function MessageThreadPanel({
|
||||
typingParentEventId={threadHead.id}
|
||||
typingRootEventId={threadHead.rootId}
|
||||
/>
|
||||
<div className="h-6 bg-background">
|
||||
{threadTypingPubkeys.length > 0 ? (
|
||||
<TypingIndicatorRow
|
||||
channel={channel}
|
||||
className="px-4 pb-1 pt-0 sm:px-6"
|
||||
currentPubkey={currentPubkey}
|
||||
profiles={profiles}
|
||||
typingPubkeys={threadTypingPubkeys}
|
||||
/>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
@@ -133,7 +133,7 @@ export const MessageTimeline = React.memo(function MessageTimeline({
|
||||
ref={scrollContainerRef}
|
||||
>
|
||||
<div
|
||||
className="mx-auto flex w-full max-w-4xl flex-col gap-2 pb-8 pt-14"
|
||||
className="mx-auto flex w-full max-w-4xl flex-col gap-2 pb-10 pt-14"
|
||||
ref={contentRef}
|
||||
>
|
||||
<div ref={topSentinelRef} aria-hidden className="h-px" />
|
||||
@@ -197,7 +197,7 @@ export const MessageTimeline = React.memo(function MessageTimeline({
|
||||
</div>
|
||||
|
||||
{!isAtBottom ? (
|
||||
<div className="pointer-events-none absolute inset-x-0 bottom-32 z-20 flex justify-center px-4">
|
||||
<div className="pointer-events-none absolute inset-x-0 bottom-36 z-20 flex justify-center px-4">
|
||||
<Button
|
||||
className="pointer-events-auto h-7 min-h-7 gap-1.5 rounded-full border-border/50 bg-background/85 px-2.5 text-[11px] font-medium text-muted-foreground shadow-sm backdrop-blur-sm hover:bg-muted/70 hover:text-foreground [&_svg]:size-3.5"
|
||||
data-testid="message-scroll-to-latest"
|
||||
|
||||
@@ -6,9 +6,11 @@ import {
|
||||
} from "@/features/profile/lib/identity";
|
||||
import { ProfileAvatar } from "@/features/profile/ui/ProfileAvatar";
|
||||
import type { Channel } from "@/shared/api/types";
|
||||
import { cn } from "@/shared/lib/cn";
|
||||
|
||||
type TypingIndicatorRowProps = {
|
||||
channel: Channel | null;
|
||||
className?: string;
|
||||
currentPubkey?: string;
|
||||
profiles?: UserProfileLookup;
|
||||
typingPubkeys: string[];
|
||||
@@ -48,6 +50,7 @@ function formatTypingLabel(names: string[]) {
|
||||
|
||||
export function TypingIndicatorRow({
|
||||
channel,
|
||||
className,
|
||||
currentPubkey,
|
||||
profiles,
|
||||
typingPubkeys,
|
||||
@@ -69,7 +72,7 @@ export function TypingIndicatorRow({
|
||||
return (
|
||||
<div
|
||||
aria-live="polite"
|
||||
className="shrink-0 bg-transparent px-4 py-2 sm:px-6"
|
||||
className={cn("shrink-0 bg-transparent px-4 py-2 sm:px-6", className)}
|
||||
{...(labels.length > 0
|
||||
? { "data-testid": "message-typing-indicator" }
|
||||
: {})}
|
||||
|
||||
Reference in New Issue
Block a user