v0.2.0: 全面代码质量优化
- ESLint flat config + Prettier + EditorConfig - Markdown处理器LRU缓存 - Zustand选择器优化减少重渲染 - CodeMirror Compartment主题热切换 - Preview防抖(150ms) + IndexedDB去抖(500ms) - 组件拆分: App.tsx 310→104行, Sidebar.tsx 244→90行 - 统一错误处理 errorHandler.ts - ConfirmDialog替代原生confirm - LoadingSpinner加载状态 - Toast多条堆叠+类型区分 - 可访问性增强(ARIA属性、键盘导航) - Vitest测试框架(78个测试用例) - Git hooks(husky + lint-staged) - 项目文档(README.md, CONTRIBUTING.md)
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
import React from 'react'
|
||||
|
||||
interface LoadingSpinnerProps {
|
||||
size?: 'small' | 'medium' | 'large'
|
||||
label?: string
|
||||
/** 是否全屏覆盖 */
|
||||
overlay?: boolean
|
||||
}
|
||||
|
||||
const sizeMap = {
|
||||
small: 16,
|
||||
medium: 24,
|
||||
large: 36
|
||||
}
|
||||
|
||||
/**
|
||||
* UX-02: 通用加载指示器组件
|
||||
*/
|
||||
export const LoadingSpinner = React.memo(function LoadingSpinner({
|
||||
size = 'medium',
|
||||
label,
|
||||
overlay = false
|
||||
}: LoadingSpinnerProps) {
|
||||
const px = sizeMap[size]
|
||||
|
||||
const spinner = (
|
||||
<div
|
||||
className={`loading-spinner loading-spinner-${size}`}
|
||||
role="status"
|
||||
aria-label={label || '加载中'}
|
||||
>
|
||||
<svg
|
||||
className="loading-spinner-svg"
|
||||
width={px}
|
||||
height={px}
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<circle
|
||||
cx="12"
|
||||
cy="12"
|
||||
r="10"
|
||||
stroke="currentColor"
|
||||
strokeWidth="3"
|
||||
strokeLinecap="round"
|
||||
opacity="0.2"
|
||||
/>
|
||||
<path
|
||||
d="M12 2a10 10 0 0 1 10 10"
|
||||
stroke="currentColor"
|
||||
strokeWidth="3"
|
||||
strokeLinecap="round"
|
||||
/>
|
||||
</svg>
|
||||
{label && <span className="loading-spinner-label">{label}</span>}
|
||||
</div>
|
||||
)
|
||||
|
||||
if (!overlay) return spinner
|
||||
|
||||
return (
|
||||
<div className="loading-overlay" aria-busy="true">
|
||||
{spinner}
|
||||
</div>
|
||||
)
|
||||
})
|
||||
|
||||
LoadingSpinner.displayName = 'LoadingSpinner'
|
||||
Reference in New Issue
Block a user