聚焦创作输入框高度变大

This commit is contained in:
北枳 2025-09-28 21:37:17 +08:00
parent dd63923e97
commit f6dff7eb49

View File

@ -244,6 +244,11 @@ export function ChatInputBox({ noData }: { noData: boolean }) {
} }
}, []); }, []);
// H5 文本输入框聚焦动画控制
const textareaRef = useRef<HTMLTextAreaElement>(null);
const [isInputFocused, setIsInputFocused] = useState(false);
const [persistedMobileMaxHeight, setPersistedMobileMaxHeight] = useState<number | null>(null);
const handleCreateVideo = async () => { const handleCreateVideo = async () => {
if (isCreating) return; // 如果正在创建中,直接返回 if (isCreating) return; // 如果正在创建中,直接返回
@ -342,23 +347,77 @@ export function ChatInputBox({ noData }: { noData: boolean }) {
<div data-alt="chat-input-box" className="flex flex-col w-full"> <div data-alt="chat-input-box" className="flex flex-col w-full">
{/* 第一行:输入框 */} {/* 第一行:输入框 */}
<div className="video-prompt-editor mb-3 relative flex flex-col gap-3 flex-1 pr-10"> <div className="video-prompt-editor mb-3 relative flex flex-col gap-3 flex-1 pr-10">
{/* 文本输入框 - 改为textarea */} {/* 文本输入框 - 改为textarea */}
<textarea <textarea
value={script} data-alt="story-input"
onChange={(e) => setScript(e.target.value)} ref={textareaRef}
placeholder="Describe the story you want to make..." value={script}
className="w-full pl-[10px] pr-[10px] py-[14px] rounded-[10px] leading-[20px] text-sm border-none bg-transparent text-white placeholder:text-white/[0.40] focus:outline-none resize-none min-h-[48px] max-h-[120px] overflow-y-auto" onChange={(e) => setScript(e.target.value)}
style={{ placeholder="Describe the story you want to make..."
minHeight: noData ? "128px": "unset" className={`w-full pl-[10px] pr-[10px] py-[14px] rounded-[10px] leading-[20px] text-sm border-none bg-transparent text-white placeholder:text-white/[0.40] focus:outline-none resize-none overflow-y-auto transition-all duration-300 ease-in-out ${isMobile ? '' : 'max-h-[120px]'}`}
}} style={{
rows={1} minHeight: noData ? "128px" : (isMobile ? (isInputFocused ? "96px" : "48px") : "unset"),
onInput={(e) => { maxHeight: isMobile ? (isInputFocused ? "200px" : (persistedMobileMaxHeight ? `${persistedMobileMaxHeight}px` : "120px")) : undefined,
const target = e.target as HTMLTextAreaElement; }}
target.style.height = "auto"; rows={1}
target.style.height = onFocus={() => {
Math.min(target.scrollHeight, 120) + "px"; if (!isMobile) return;
}} setIsInputFocused(true);
/> const el = textareaRef.current;
if (el) {
const limit = 200;
// 以当前高度为起点,过渡到目标高度
const start = `${el.getBoundingClientRect().height}px`;
const end = `${Math.min(Math.max(el.scrollHeight, 96), limit)}px`;
el.style.height = start;
void el.offsetHeight;
el.style.height = end;
}
}}
onBlur={() => {
if (!isMobile) return;
setIsInputFocused(false);
const el = textareaRef.current;
if (el) {
const baseLimit = 120;
const contentHeight = el.scrollHeight;
const currentHeight = el.getBoundingClientRect().height;
// 若内容高度已超过基础高度,则保持较大高度,不回落
if (contentHeight > baseLimit || currentHeight > baseLimit) {
setPersistedMobileMaxHeight(Math.min(contentHeight, 200));
el.style.height = `${Math.min(contentHeight, 200)}px`;
} else {
const start = `${currentHeight}px`;
const end = `${Math.min(contentHeight, baseLimit)}px`;
el.style.height = start;
void el.offsetHeight;
el.style.height = end;
setPersistedMobileMaxHeight(null);
}
}
}}
onInput={(e) => {
const target = e.target as HTMLTextAreaElement;
const limit = isMobile && isInputFocused ? 200 : (persistedMobileMaxHeight ?? 120);
target.style.height = "auto";
target.style.height = Math.min(target.scrollHeight, limit) + "px";
}}
onTransitionEnd={() => {
// 过渡结束后清理高度,避免下次动画受限
if (!isMobile) return;
if (!isInputFocused) {
const el = textareaRef.current;
if (el) {
// 若已记录持久高度则保持,不清理;否则清理
if (persistedMobileMaxHeight) {
el.style.height = `${persistedMobileMaxHeight}px`;
} else {
el.style.height = "";
}
}
}
}}
/>
</div> </div>
{/* 第二行功能按钮和Action按钮 - 同一行 */} {/* 第二行功能按钮和Action按钮 - 同一行 */}