聚焦创作输入框高度变大

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 () => {
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 className="video-prompt-editor mb-3 relative flex flex-col gap-3 flex-1 pr-10">
{/* 文本输入框 - 改为textarea */}
<textarea
value={script}
onChange={(e) => setScript(e.target.value)}
placeholder="Describe the story you want to make..."
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"
style={{
minHeight: noData ? "128px": "unset"
}}
rows={1}
onInput={(e) => {
const target = e.target as HTMLTextAreaElement;
target.style.height = "auto";
target.style.height =
Math.min(target.scrollHeight, 120) + "px";
}}
/>
{/* 文本输入框 - 改为textarea */}
<textarea
data-alt="story-input"
ref={textareaRef}
value={script}
onChange={(e) => setScript(e.target.value)}
placeholder="Describe the story you want to make..."
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={{
minHeight: noData ? "128px" : (isMobile ? (isInputFocused ? "96px" : "48px") : "unset"),
maxHeight: isMobile ? (isInputFocused ? "200px" : (persistedMobileMaxHeight ? `${persistedMobileMaxHeight}px` : "120px")) : undefined,
}}
rows={1}
onFocus={() => {
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>
{/* 第二行功能按钮和Action按钮 - 同一行 */}