feat(ui): 强化 AI 工作中动效——构思占位/流式进度条/波动三点/转圈
- 动效基元:ai-dot 波动(三点竖跳)、ai-stream 不确定进度条、ai-breathe 呼吸微光(均带 reduced-motion 回退) - ThinkingIndicator 升级为明显波动;新增 Spinner / StreamingBar / GenerationSkeleton 原子件;Button 加 loading 态 - 写作台:首 token 前正文区『AI 正在构思本章…』占位(补最大缺口,不再空白像卡死)+ 流式顶部进度条 - 整章重写流式进度条;续写/润色忙碌骨架 + 触发键转圈;生成器/角色/世界观改用 Button loading
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
import { useEffect, useRef } from "react";
|
||||
|
||||
import { cn, focusRing, proseBody } from "@/lib/ui/variants";
|
||||
import { ThinkingPlaceholder } from "./ThinkingPlaceholder";
|
||||
|
||||
export interface EditorSelection {
|
||||
start: number;
|
||||
@@ -14,6 +15,9 @@ interface EditorProps {
|
||||
value: string;
|
||||
onChange: (value: string) => void;
|
||||
streaming: boolean;
|
||||
// 构思中(流式已开始但首 token 未到):在正文区覆盖「AI 正在构思本章…」占位,
|
||||
// 首个 token 到达即消失换成正文。纯展示层,不触碰流式逻辑。
|
||||
isThinking?: boolean;
|
||||
// 选区变化上报(供「润色选段」等选区级 AI 动作取材)。空选区也会上报(start===end)。
|
||||
onSelectionChange?: (selection: EditorSelection) => void;
|
||||
}
|
||||
@@ -24,6 +28,7 @@ export function Editor({
|
||||
value,
|
||||
onChange,
|
||||
streaming,
|
||||
isThinking = false,
|
||||
onSelectionChange,
|
||||
}: EditorProps) {
|
||||
const ref = useRef<HTMLTextAreaElement>(null);
|
||||
@@ -46,7 +51,7 @@ export function Editor({
|
||||
}, [value]);
|
||||
|
||||
return (
|
||||
<div className="mx-auto max-w-prose">
|
||||
<div className="relative mx-auto max-w-prose">
|
||||
<label htmlFor="chapter-editor" className="sr-only">
|
||||
正文编辑器
|
||||
</label>
|
||||
@@ -65,12 +70,13 @@ export function Editor({
|
||||
focusRing,
|
||||
)}
|
||||
/>
|
||||
{streaming ? (
|
||||
{streaming && !isThinking ? (
|
||||
<span
|
||||
className="typewriter-cursor ml-0.5 inline-block h-[1.2em] w-[2px] translate-y-1 bg-cinnabar align-middle"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
) : null}
|
||||
{isThinking ? <ThinkingPlaceholder /> : null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user