* feat(canvas): 面板层级管理优化 - 五层Elevation+渐进式三区+进度增强 #98 #94 基于 Wayfinder 地图 #98 决议执行面板层级管理优化: 1. 五层 Elevation 体系(决策1) - 画布组件 z-index 硬编码值全部迁移到 token - L0 画布层 → L1 工具层 → L2 面板层 → L3 对话框层 → L4 通知层 - 涉及 14 个 .tsx 文件,0 处 z-[N] 硬编码残留 2. prompt 面板渐进式三区(决策2) - B区参数区改为手风琴折叠模式(默认折叠) - 新增 SlidersHorizontal + ChevronDown 图标切换 - 点击展开 video 工具参数,收起后释放视觉空间 - A区核心区(prompt+生成)始终展开 3. 任务进度条增强(决策3) - 进度条高度 1px→1.5px,视觉更醒目 - 新增 shimmer 扫描动画(running 态,1.4s/cycle) - 新增百分比数字显示(tabular-nums 等宽数字) - 新增 indeterminate 模式(无百分比时循环扫描) - 尊重 prefers-reduced-motion(reducedMotion 时禁用动画) 4. CSS 动画 - 新增 @keyframes canvas-task-progress-shimmer - .canvas-task-progress-shimmer 类 Closes #98 * refactor(canvas): z-index 全量迁移到五层Elevation token #98 #94 补全 #98 五层 Elevation 体系的剩余硬编码 z-index 清理: - 三个设置弹层(图/音/视频)zIndex:1200 → var(--z-popover) - model-setup-guide z-[900] → var(--z-toast) - 项目侧栏 z-30 → var(--z-panel),章节预览 z-50 → var(--z-panel-floating) - shared 页头/缩放控件/访客提示 z-[80]/z-[70] → var(--z-panel-floating),右键菜单 z-[90] → var(--z-modal) - project 缩放控件容器 z-50 → var(--z-panel),绘图加载遮罩 z-[500] → var(--z-toast) - 反馈面板 z-[90] → var(--z-panel-floating) 共 16 处全局浮层 z-index 迁移到 token,消除层级冲突隐患。 --------- Co-authored-by: sikongyue <3155157671@qq.com>
43 lines
2.8 KiB
TypeScript
43 lines
2.8 KiB
TypeScript
import { motion, useReducedMotion } from "motion/react";
|
||
import { ArrowRight, Sparkles, X } from "lucide-react";
|
||
import { useState } from "react";
|
||
|
||
import { aceternityMotion } from "@/lib/aceternity-motion";
|
||
import { navigateToSettings } from "@/lib/settings-navigation";
|
||
import { useConfigStore } from "@/stores/use-config-store";
|
||
import { useUserStore } from "@/stores/use-user-store";
|
||
|
||
export function ModelSetupGuide({ hidden = false }: { hidden?: boolean }) {
|
||
const reducedMotion = useReducedMotion();
|
||
const [dismissed, setDismissed] = useState(false);
|
||
const registrationGuide = typeof window !== "undefined" && window.sessionStorage.getItem("infinite-canvas:model-setup-guide") === "1";
|
||
const hydrated = useUserStore((state) => state.hydrated);
|
||
const user = useUserStore((state) => state.user);
|
||
const models = useConfigStore((state) => state.config.models);
|
||
if (hidden || dismissed || !hydrated || !user || user.role === "admin" || (!registrationGuide && models.length > 0)) return null;
|
||
|
||
const close = () => {
|
||
window.sessionStorage.removeItem("infinite-canvas:model-setup-guide");
|
||
setDismissed(true);
|
||
};
|
||
|
||
const openModels = () => {
|
||
close();
|
||
navigateToSettings({ section: "models" });
|
||
};
|
||
|
||
return (
|
||
<motion.aside initial={reducedMotion ? false : { opacity: 0, y: 14, scale: 0.97 }} animate={{ opacity: 1, y: 0, scale: 1 }} transition={{ duration: aceternityMotion.duration.panel, ease: aceternityMotion.easing.enter }} className="fixed bottom-5 right-5 z-[var(--z-toast)] w-[min(360px,calc(100vw-32px))] overflow-hidden rounded-2xl border border-border/70 bg-background/92 shadow-[0_24px_70px_rgba(15,23,42,.20)] backdrop-blur-2xl dark:shadow-[0_28px_80px_rgba(0,0,0,.48)]">
|
||
<div className="flex items-start gap-3 p-4">
|
||
<span className="grid size-9 shrink-0 place-items-center rounded-xl border border-amber-400/25 bg-amber-400/10 text-amber-600 dark:text-amber-300"><Sparkles className="size-4" /></span>
|
||
<button type="button" className="min-w-0 flex-1 text-left" onClick={openModels}>
|
||
<span className="block text-sm font-semibold">先选择创作模型</span>
|
||
<span className="mt-1 block text-xs leading-5 text-foreground/55">配置生图、视频和文本的默认模型,价格会在选择时显示。</span>
|
||
<span className="mt-3 inline-flex items-center gap-1.5 text-xs font-semibold text-foreground">打开模型选择 <ArrowRight className="size-3.5" /></span>
|
||
</button>
|
||
<button type="button" className="grid size-7 shrink-0 place-items-center rounded-full text-foreground/40 transition hover:bg-muted hover:text-foreground" onClick={close} aria-label="关闭模型配置引导"><X className="size-3.5" /></button>
|
||
</div>
|
||
</motion.aside>
|
||
);
|
||
}
|