feat(chat): expand empty input actions

This commit is contained in:
2026-06-22 19:14:27 +08:00
parent e68cabdc54
commit cebc8f7443
6 changed files with 157 additions and 7 deletions
+51 -6
View File
@@ -23,11 +23,13 @@
import { useRef, useState } from "react";
import { useChatDispatch } from "@/stores/chat/chat-context";
import { useUserState } from "@/stores/user/user-context";
import { Logger } from "@/utils";
import { ChatInputActionPanel } from "./chat-input-action-panel";
import { ChatInputTextField } from "./chat-input-text-field";
import { ChatSendButton } from "./chat-send-button";
import styles from "./chat-input-bar.module.css";
import { Logger } from "@/utils";
const log = new Logger("AppChatComponentsChatInputBar");
@@ -37,11 +39,22 @@ export interface ChatInputBarProps {
export function ChatInputBar({ disabled = false }: ChatInputBarProps) {
const dispatch = useChatDispatch();
const { currentUser } = useUserState();
const [input, setInput] = useState("");
const [isFocused, setIsFocused] = useState(false);
const [isActionPanelOpen, setIsActionPanelOpen] = useState(false);
const textareaRef = useRef<HTMLTextAreaElement>(null);
const hasContent = input.trim().length > 0;
const isActive = isFocused || isActionPanelOpen;
const voiceMinutesRemaining = currentUser?.voiceMinutesRemaining ?? 0;
const handleInputChange = (value: string) => {
setInput(value);
if (value.trim().length > 0) {
setIsActionPanelOpen(false);
}
};
const handleSend = () => {
if (!hasContent) return;
@@ -57,23 +70,55 @@ export function ChatInputBar({ disabled = false }: ChatInputBarProps) {
textareaRef.current?.focus();
};
const handleActionButtonClick = () => {
if (hasContent) {
handleSend();
return;
}
textareaRef.current?.blur();
setIsFocused(false);
setIsActionPanelOpen((open) => !open);
};
const handleVoiceMessageClick = () => {
log.debug("[chat-input-bar] voice message action clicked", {
voiceMinutesRemaining,
});
};
return (
<div className={`${styles.bar} ${isFocused ? styles.barFocused : ""}`}>
<div className={`${styles.row} ${isFocused ? styles.rowFocused : ""}`}>
<div
className={`${styles.bar} ${isActive ? styles.barFocused : ""} ${
isActionPanelOpen ? styles.barExpanded : ""
}`}
>
<div
className={`${styles.row} ${isActive ? styles.rowFocused : ""} ${
isActionPanelOpen ? styles.rowExpanded : ""
}`}
>
<ChatInputTextField
ref={textareaRef}
value={input}
onChange={setInput}
onChange={handleInputChange}
onSubmit={handleSend}
onFocusChange={setIsFocused}
disabled={disabled}
/>
<ChatSendButton
disabled={!hasContent || disabled}
disabled={disabled}
hasContent={hasContent}
onClick={handleSend}
isExpanded={isActionPanelOpen}
onClick={handleActionButtonClick}
/>
</div>
{isActionPanelOpen ? (
<ChatInputActionPanel
voiceMinutesRemaining={voiceMinutesRemaining}
onVoiceMessageClick={handleVoiceMessageClick}
/>
) : null}
</div>
);
}