From e830575efcd6aa09ade3a8d3ad168d7798277e38 Mon Sep 17 00:00:00 2001 From: Jiayuan Zhang Date: Mon, 20 Apr 2026 18:19:40 +0800 Subject: [PATCH] feat(issues): add expand toggle to comment and reply editors (#1386) Mirrors the new-issue modal's expand behavior on the inline comment and reply editors so users can compose long text without feeling cramped. --- .../views/issues/components/comment-input.tsx | 27 +++++++++++++++-- .../views/issues/components/reply-input.tsx | 29 ++++++++++++++++--- 2 files changed, 50 insertions(+), 6 deletions(-) diff --git a/packages/views/issues/components/comment-input.tsx b/packages/views/issues/components/comment-input.tsx index 4f4bf3b86..daecb405a 100644 --- a/packages/views/issues/components/comment-input.tsx +++ b/packages/views/issues/components/comment-input.tsx @@ -1,8 +1,10 @@ "use client"; import { useRef, useState, useCallback } from "react"; -import { ArrowUp, Loader2 } from "lucide-react"; +import { ArrowUp, Loader2, Maximize2, Minimize2 } from "lucide-react"; import { Button } from "@multica/ui/components/ui/button"; +import { Tooltip, TooltipTrigger, TooltipContent } from "@multica/ui/components/ui/tooltip"; +import { cn } from "@multica/ui/lib/utils"; import { ContentEditor, type ContentEditorRef, useFileDropZone, FileDropOverlay } from "../../editor"; import { FileUploadButton } from "@multica/ui/components/common/file-upload-button"; import { useFileUpload } from "@multica/core/hooks/use-file-upload"; @@ -17,6 +19,7 @@ function CommentInput({ issueId, onSubmit }: CommentInputProps) { const editorRef = useRef(null); const [isEmpty, setIsEmpty] = useState(true); const [submitting, setSubmitting] = useState(false); + const [isExpanded, setIsExpanded] = useState(false); const uploadMapRef = useRef>(new Map()); const { uploadWithToast } = useFileUpload(api); const { isDragOver, dropZoneProps } = useFileDropZone({ @@ -53,7 +56,10 @@ function CommentInput({ issueId, onSubmit }: CommentInputProps) { return (
+ + { + setIsExpanded((v) => !v); + editorRef.current?.focus(); + }} + className="rounded-sm p-1.5 text-muted-foreground opacity-70 hover:opacity-100 hover:bg-accent/60 transition-all cursor-pointer" + > + {isExpanded ? : } + + } + /> + {isExpanded ? "Collapse" : "Expand"} + editorRef.current?.uploadFile(file)} diff --git a/packages/views/issues/components/reply-input.tsx b/packages/views/issues/components/reply-input.tsx index 6006edfd9..40a22a514 100644 --- a/packages/views/issues/components/reply-input.tsx +++ b/packages/views/issues/components/reply-input.tsx @@ -1,9 +1,10 @@ "use client"; import { useRef, useState, useEffect, useCallback } from "react"; -import { ArrowUp, Loader2 } from "lucide-react"; +import { ArrowUp, Loader2, Maximize2, Minimize2 } from "lucide-react"; import { ContentEditor, type ContentEditorRef, useFileDropZone, FileDropOverlay } from "../../editor"; import { FileUploadButton } from "@multica/ui/components/common/file-upload-button"; +import { Tooltip, TooltipTrigger, TooltipContent } from "@multica/ui/components/ui/tooltip"; import { ActorAvatar } from "../../common/actor-avatar"; import { useFileUpload } from "@multica/core/hooks/use-file-upload"; import { api } from "@multica/core/api"; @@ -37,6 +38,7 @@ function ReplyInput({ const editorRef = useRef(null); const measureRef = useRef(null); const [isEmpty, setIsEmpty] = useState(true); + const [hasOverflowContent, setHasOverflowContent] = useState(false); const [isExpanded, setIsExpanded] = useState(false); const [submitting, setSubmitting] = useState(false); const uploadMapRef = useRef>(new Map()); @@ -50,7 +52,7 @@ function ReplyInput({ if (!el) return; const observer = new ResizeObserver((entries) => { const entry = entries[0]; - if (entry) setIsExpanded(entry.contentRect.height > 32); + if (entry) setHasOverflowContent(entry.contentRect.height > 32); }); observer.observe(el); return () => observer.disconnect(); @@ -97,8 +99,10 @@ function ReplyInput({ {...dropZoneProps} className={cn( "relative min-w-0 flex-1 flex flex-col", - size === "sm" ? "max-h-40" : "max-h-56", - isExpanded && "pb-7", + isExpanded + ? "h-[60vh]" + : size === "sm" ? "max-h-40" : "max-h-56", + (hasOverflowContent || isExpanded) && "pb-7", )} >
@@ -115,6 +119,23 @@ function ReplyInput({
+ + { + setIsExpanded((v) => !v); + editorRef.current?.focus(); + }} + className="inline-flex h-6 w-6 items-center justify-center rounded-sm opacity-70 hover:opacity-100 hover:bg-accent/60 transition-all cursor-pointer" + > + {isExpanded ? : } + + } + /> + {isExpanded ? "Collapse" : "Expand"} + editorRef.current?.uploadFile(file)}