feat: enhance ecommerce UI with typewriter animation, icon buttons, responsive layout, and refined design tokens
- EcommercePage.tsx: Add typewriter animation (useTypewriter hook) for slogan text with blinking cursor; replace text-based add/delete buttons with Ant Design icons (CloudUploadOutlined, DeleteOutlined); make command history panel responsive to window width (auto-collapse ≤1180px); update button labels from generic "添加" to context-specific "上传商品图" / "上传素材" - New useTypewriter.ts hook: Character-by-character typewriter animation with configurable speed and pause-before-loop, auto-resets on text change - reset.css: Add comprehensive HTML/body typography baseline (font-size, text-rendering, font-smoothing, line-height); extend reset coverage to select/canvas/svg elements; add overflow-wrap:anywhere for text-bearing elements; add min-width:0 to prevent form element overflow - primitives.css: Add reusable typography utility classes (ui-page-title, ui-section-title, ui-body-copy) with design token references - tokens.css: Expand design token set for typography scales, font weights, and leading values - ecommerce-standalone.css: Add 689 lines of standalone ecommerce page styles - Page CSS (ecommerce, image-workbench, more-tools, more, script-tokens, script-tokens-v5, studio-layout): Enhanced visual styles and layout refinements across all pages - app-shell.css: Shell-level layout and styling improvements
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
import { useState, useEffect, useRef } from "react";
|
||||
|
||||
/**
|
||||
* 打字机动画 Hook:逐字显示文本,完成后停顿指定时间再重复。
|
||||
*
|
||||
* @param text 要显示的文本
|
||||
* @param typingSpeed 每个字的间隔(ms),默认 120
|
||||
* @param pauseDuration 打完后的停顿时间(ms),默认 5000
|
||||
* @returns 当前已显示的文字
|
||||
*/
|
||||
export function useTypewriter(text: string, typingSpeed = 120, pauseDuration = 5000) {
|
||||
const [displayText, setDisplayText] = useState("");
|
||||
const indexRef = useRef(0);
|
||||
const pausingRef = useRef(false);
|
||||
const restartTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
// 重置所有状态
|
||||
indexRef.current = 0;
|
||||
pausingRef.current = false;
|
||||
setDisplayText("");
|
||||
if (restartTimerRef.current) clearTimeout(restartTimerRef.current);
|
||||
|
||||
const interval = setInterval(() => {
|
||||
if (pausingRef.current) return;
|
||||
|
||||
if (indexRef.current < text.length) {
|
||||
indexRef.current++;
|
||||
setDisplayText(text.slice(0, indexRef.current));
|
||||
} else {
|
||||
// 打字完成,进入停顿
|
||||
pausingRef.current = true;
|
||||
restartTimerRef.current = setTimeout(() => {
|
||||
indexRef.current = 0;
|
||||
pausingRef.current = false;
|
||||
setDisplayText("");
|
||||
}, pauseDuration);
|
||||
}
|
||||
}, typingSpeed);
|
||||
|
||||
return () => {
|
||||
clearInterval(interval);
|
||||
if (restartTimerRef.current) clearTimeout(restartTimerRef.current);
|
||||
};
|
||||
}, [text, typingSpeed, pauseDuration]);
|
||||
|
||||
return displayText;
|
||||
}
|
||||
Reference in New Issue
Block a user