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:
1 parent
5d00adc1a5
commit
76c67b492e
216 files changed
+12454
-13976
No files matched your search
@@ -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',
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -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 }
|
||||
@@ -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
|
||||
@@ -1,2 +1,2 @@
|
||||
export * from "./button";
|
||||
export * from "./button.types";
|
||||
export * from './button'
|
||||
export * from './button.types'
|
||||
Reference in new issue
Block a user