From cebc8f7443e3aed39fbf6cd6ac8ba55aa034b1ff Mon Sep 17 00:00:00 2001 From: chenhang Date: Mon, 22 Jun 2026 19:14:27 +0800 Subject: [PATCH] feat(chat): expand empty input actions --- .../chat-input-action-panel.module.css | 50 ++++++++++++++++ .../components/chat-input-action-panel.tsx | 37 ++++++++++++ .../chat/components/chat-input-bar.module.css | 13 +++++ src/app/chat/components/chat-input-bar.tsx | 57 +++++++++++++++++-- src/app/chat/components/chat-send-button.tsx | 6 +- src/app/chat/components/index.ts | 1 + 6 files changed, 157 insertions(+), 7 deletions(-) create mode 100644 src/app/chat/components/chat-input-action-panel.module.css create mode 100644 src/app/chat/components/chat-input-action-panel.tsx diff --git a/src/app/chat/components/chat-input-action-panel.module.css b/src/app/chat/components/chat-input-action-panel.module.css new file mode 100644 index 00000000..dc2bcc5f --- /dev/null +++ b/src/app/chat/components/chat-input-action-panel.module.css @@ -0,0 +1,50 @@ +.panel { + min-height: 170px; + padding: 24px 16px 20px; + border-top: 1px solid rgba(246, 87, 160, 0.14); + background: #fff1f4; +} + +.voiceCard { + width: 142px; + min-height: 153px; + padding: 12px 12px 14px; + border: 1px solid rgba(30, 30, 30, 0.08); + border-radius: 18px; + background: #ffffff; + box-shadow: 0 1px 2px rgba(30, 30, 30, 0.03); + color: #1e1e1e; + cursor: pointer; + display: flex; + flex-direction: column; + align-items: center; + justify-content: flex-start; +} + +.voiceCard:focus-visible { + outline: 2px solid var(--color-accent, #f84d96); + outline-offset: 3px; +} + +.voiceIcon { + display: block; + width: 78px; + height: 78px; + object-fit: contain; +} + +.voiceTitle, +.voiceMinutes { + font-family: var(--font-athelas), Athelas, serif; + font-size: 14px; + line-height: 1.08; + text-align: center; +} + +.voiceTitle { + margin-top: 8px; +} + +.voiceMinutes { + color: var(--color-accent, #f84d96); +} diff --git a/src/app/chat/components/chat-input-action-panel.tsx b/src/app/chat/components/chat-input-action-panel.tsx new file mode 100644 index 00000000..44388111 --- /dev/null +++ b/src/app/chat/components/chat-input-action-panel.tsx @@ -0,0 +1,37 @@ +"use client"; + +import Image from "next/image"; + +import styles from "./chat-input-action-panel.module.css"; + +export interface ChatInputActionPanelProps { + voiceMinutesRemaining: number; + onVoiceMessageClick?: () => void; +} + +export function ChatInputActionPanel({ + voiceMinutesRemaining, + onVoiceMessageClick, +}: ChatInputActionPanelProps) { + return ( +
+ +
+ ); +} diff --git a/src/app/chat/components/chat-input-bar.module.css b/src/app/chat/components/chat-input-bar.module.css index 4dc0a361..850c2856 100644 --- a/src/app/chat/components/chat-input-bar.module.css +++ b/src/app/chat/components/chat-input-bar.module.css @@ -15,6 +15,13 @@ box-shadow: 0 4px 12px var(--color-input-box-shadow, rgba(0, 0, 0, 0.1)); } +.barExpanded { + padding-right: 0; + padding-bottom: 0; + padding-left: 0; + background: #fff1f4; +} + /* 内层:白底 + 大圆角(Dart AppRadius.radius32)+ focused 时 accent 边框 */ .row { display: flex; @@ -30,3 +37,9 @@ .rowFocused { border-color: var(--color-accent, #f84d96); } + +.rowExpanded { + margin: 0 var(--spacing-md, 12px) var(--spacing-md, 12px); + border-color: #ff8fc7; + box-shadow: 0 2px 10px rgba(246, 87, 160, 0.16); +} diff --git a/src/app/chat/components/chat-input-bar.tsx b/src/app/chat/components/chat-input-bar.tsx index 233b478a..2a4f7085 100644 --- a/src/app/chat/components/chat-input-bar.tsx +++ b/src/app/chat/components/chat-input-bar.tsx @@ -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(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 ( -
-
+
+
+ {isActionPanelOpen ? ( + + ) : null}
); } diff --git a/src/app/chat/components/chat-send-button.tsx b/src/app/chat/components/chat-send-button.tsx index 913fddbe..fd03bbd4 100644 --- a/src/app/chat/components/chat-send-button.tsx +++ b/src/app/chat/components/chat-send-button.tsx @@ -17,15 +17,18 @@ import styles from "./chat-send-button.module.css"; export interface ChatSendButtonProps { disabled: boolean; hasContent: boolean; + isExpanded?: boolean; onClick: () => void; } export function ChatSendButton({ disabled, hasContent, + isExpanded = false, onClick, }: ChatSendButtonProps) { const Icon = hasContent ? ArrowUp : Plus; + const ariaLabel = hasContent ? "Send message" : "Open chat actions"; return ( diff --git a/src/app/chat/components/index.ts b/src/app/chat/components/index.ts index e0ca93c6..c522a0b5 100644 --- a/src/app/chat/components/index.ts +++ b/src/app/chat/components/index.ts @@ -6,6 +6,7 @@ export * from "./ai-disclosure-banner"; export * from "./browser-hint-overlay"; export * from "./chat-area"; export * from "./chat-header"; +export * from "./chat-input-action-panel"; export * from "./chat-input-bar"; export * from "./chat-input-text-field"; export * from "./chat-quota-exhausted-banner";