feat: 更新 ESLint 和 Prettier 配置,增强代码质量管理

- 在 .gitignore 中添加 public/audio/* 以忽略音频文件。
- 更新 bun.lock,添加 eslint-config-prettier 和 eslint-plugin-prettier 依赖,确保 ESLint 与 Prettier 的兼容性。
- 修改 eslint.config.ts,整合 Prettier 规则,优化代码风格一致性。
- 在 package.json 中添加 lint:fix 和 format 脚本,简化代码格式化和修复流程。
- 更新 tailwind.config.ts 和其他组件文件,统一代码风格,提升可读性。
This commit is contained in:
zhongyidian committed 2026-03-05 13:50:47 +08:00
1 parent 5d00adc1a5
commit 76c67b492e
216 files changed
+12454 -13976

No files matched your search

+27 -27
View File
@@ -1,56 +1,56 @@
import type { Meta, StoryObj } from "@storybook/react";
import { Button, ImageButton } from "./button";
import type { Meta, StoryObj } from '@storybook/react'
import { Button, ImageButton } from './button'
const meta: Meta<typeof Button> = {
title: "Components/Button",
title: 'Components/Button',
component: Button,
tags: ["autodocs"],
tags: ['autodocs'],
argTypes: {
variant: {
control: { type: "select" },
options: ["primary", "secondary", "ghost"],
control: { type: 'select' },
options: ['primary', 'secondary', 'ghost'],
},
},
};
}
export default meta;
export default meta
type Story = StoryObj<typeof Button>;
type Story = StoryObj<typeof Button>
export const Primary: Story = {
args: {
variant: "primary",
children: "按钮",
variant: 'primary',
children: '按钮',
},
};
}
export const Secondary: Story = {
args: {
variant: "secondary",
children: "次要按钮",
variant: 'secondary',
children: '次要按钮',
},
};
}
export const Ghost: Story = {
args: {
variant: "ghost",
children: "幽灵按钮",
variant: 'ghost',
children: '幽灵按钮',
},
};
}
export const Disabled: Story = {
args: {
disabled: true,
children: "禁用状态",
children: '禁用状态',
},
};
}
export const Loading: Story = {
args: {
loading: true,
children: "加载中...",
children: '加载中...',
},
};
}
export const WithImage: Story = {
render: () => (
@@ -64,12 +64,12 @@ export const WithImage: Story = {
/>
</div>
),
};
}
export const Playground: Story = {
args: {
variant: "primary",
children: "点击我",
className: "px-8 py-3 text-lg",
variant: 'primary',
children: '点击我',
className: 'px-8 py-3 text-lg',
},
};
}
+43 -51
View File
@@ -1,6 +1,6 @@
import { forwardRef, useState, useEffect } from "react";
import { cn } from "@/lib/utils";
import type { BaseButtonProps, ImageButtonProps } from "./button.types";
import { forwardRef, useState, useEffect } from 'react'
import { cn } from '@/lib/utils'
import type { BaseButtonProps, ImageButtonProps } from './button.types'
/**
* 基础按钮组件
@@ -9,44 +9,39 @@ const Button = forwardRef<HTMLButtonElement, BaseButtonProps>(
(
{
children,
className = "",
variant = "primary",
className = '',
variant = 'primary',
disabled = false,
loading = false,
type = "button",
type = 'button',
...props
},
ref
) => {
const baseClasses =
"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none";
'inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none'
const variantClasses = {
primary: "bg-primary text-primary-foreground hover:bg-primary/90",
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
ghost: "hover:bg-accent hover:text-accent-foreground",
};
primary: 'bg-primary text-primary-foreground hover:bg-primary/90',
secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',
ghost: 'hover:bg-accent hover:text-accent-foreground',
}
return (
<button
ref={ref}
type={type as "button" | "submit" | "reset" | undefined}
className={cn(
baseClasses,
variantClasses[variant],
"px-4 py-2",
className
)}
type={type as 'button' | 'submit' | 'reset' | undefined}
className={cn(baseClasses, variantClasses[variant], 'px-4 py-2', className)}
disabled={disabled || loading}
{...props}
>
{loading ? "加载中..." : children}
{loading ? '加载中...' : children}
</button>
);
)
}
);
)
Button.displayName = "Button";
Button.displayName = 'Button'
/**
* 图片按钮组件
@@ -57,50 +52,50 @@ const ImageButton = forwardRef<HTMLButtonElement, ImageButtonProps>(
src,
alt,
hoverSrc,
width = "auto",
height = "auto",
className = "",
width = 'auto',
height = 'auto',
className = '',
disabled = false,
loading = false,
type = "button",
type = 'button',
onMouseEnter,
onMouseLeave,
...props
},
ref
) => {
const [isHovered, setIsHovered] = useState(false);
const [imageSrc, setImageSrc] = useState(src);
const [isHovered, setIsHovered] = useState(false)
const [imageSrc, setImageSrc] = useState(src)
useEffect(() => {
if (hoverSrc) {
const img = new Image();
img.src = hoverSrc;
const img = new Image()
img.src = hoverSrc
}
}, [hoverSrc]);
}, [hoverSrc])
const handleMouseEnter = (e: React.MouseEvent<HTMLButtonElement>) => {
setIsHovered(true);
setIsHovered(true)
if (hoverSrc) {
setImageSrc(hoverSrc);
setImageSrc(hoverSrc)
}
onMouseEnter?.(e);
};
onMouseEnter?.(e)
}
const handleMouseLeave = (e: React.MouseEvent<HTMLButtonElement>) => {
setIsHovered(false);
setImageSrc(src);
onMouseLeave?.(e);
};
setIsHovered(false)
setImageSrc(src)
onMouseLeave?.(e)
}
return (
<button
ref={ref}
type={type as "button" | "submit" | "reset" | undefined}
type={type as 'button' | 'submit' | 'reset' | undefined}
className={cn(
"transition-opacity hover:opacity-90 active:opacity-80",
"focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary",
"disabled:opacity-50 disabled:cursor-not-allowed",
'transition-opacity hover:opacity-90 active:opacity-80',
'focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary',
'disabled:opacity-50 disabled:cursor-not-allowed',
className
)}
disabled={disabled || loading}
@@ -113,17 +108,14 @@ const ImageButton = forwardRef<HTMLButtonElement, ImageButtonProps>(
alt={alt}
width={width}
height={height}
className={cn(
"object-contain transition-transform",
isHovered && "transform scale-105"
)}
className={cn('object-contain transition-transform', isHovered && 'transform scale-105')}
draggable="false"
/>
</button>
);
)
}
);
)
ImageButton.displayName = "ImageButton";
ImageButton.displayName = 'ImageButton'
export { Button, ImageButton };
export { Button, ImageButton }
+13 -14
View File
@@ -1,30 +1,29 @@
import type { ButtonHTMLAttributes, ReactNode } from "react";
import type { ButtonHTMLAttributes, ReactNode } from 'react'
/** 基础按钮属性 */
export interface BaseButtonProps
extends ButtonHTMLAttributes<HTMLButtonElement> {
export interface BaseButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
/** 是否显示加载状态 */
loading?: boolean;
loading?: boolean
/** 按钮变体 */
variant?: "primary" | "secondary" | "ghost";
variant?: 'primary' | 'secondary' | 'ghost'
/** 自定义类名 */
className?: string;
className?: string
/** 子元素 */
children: ReactNode;
children: ReactNode
}
/** 图片按钮属性 */
export interface ImageButtonProps extends Omit<BaseButtonProps, "children"> {
export interface ImageButtonProps extends Omit<BaseButtonProps, 'children'> {
/** 图片URL */
src: string;
src: string
/** 图片替代文本 */
alt: string;
alt: string
/** 图片宽度 */
width?: number | string;
width?: number | string
/** 图片高度 */
height?: number | string;
height?: number | string
/** 悬停时显示的图片URL */
hoverSrc?: string;
hoverSrc?: string
}
export type ButtonProps = BaseButtonProps | ImageButtonProps;
export type ButtonProps = BaseButtonProps | ImageButtonProps
+2 -2
View File
@@ -1,2 +1,2 @@
export * from "./button";
export * from "./button.types";
export * from './button'
export * from './button.types'