refactor: 重构 Tailwind 配置以支持模块化和共享主题

- 更新 components.json,修改 CSS 文件路径为 src/styles/shell.css。
- 移除 tailwind.config.js 中的冗余配置,改为导入 tailwind.shell.config.js。
- 新增 tailwind.pages.config.js 和 tailwind.shared.js,集中管理主题和样式配置。
- 更新多个组件以使用新的样式类和配置,提升代码一致性和可维护性。
This commit is contained in:
2026-06-30 23:15:35 +08:00
parent 17a4dbd8a7
commit 6975e38f79
24 changed files with 236 additions and 87 deletions
+1 -5
View File
@@ -57,11 +57,7 @@ export const CopyButton: React.FC<CopyButtonProps> = ({
className={cn(className, copied && 'text-emerald-500')}
{...props}
>
{copied ? (
<Check className="h-[1.2em] w-[1.2em]" />
) : (
<Copy className="h-[1.2em] w-[1.2em]" />
)}
{copied ? <Check className="h-4 w-4" /> : <Copy className="h-4 w-4" />}
</Button>
);
};
+1 -3
View File
@@ -30,9 +30,7 @@ export function ErrorFallback({
<div
className={cn(
'flex flex-col items-center justify-center',
isApp
? 'mt-16 mx-auto max-w-md'
: 'flex-1 p-6 min-h-[300px] animate-in fade-in zoom-in-95 duration-200',
isApp ? 'mt-16 mx-auto max-w-md' : 'flex-1 p-6 min-h-[300px] fade-in-zoom-95',
className,
)}
>
+1 -1
View File
@@ -46,7 +46,7 @@ function ToolPageSkeleton() {
<div className="w-24 h-9 bg-muted rounded-lg animate-pulse" />
<div className="w-20 h-9 bg-muted rounded-lg animate-pulse" />
<div className="flex-1" />
<div className="w-22 h-9 bg-muted rounded-lg animate-pulse" />
<div className="w-24 h-9 bg-muted rounded-lg animate-pulse" />
</div>
{/* 结果区域 */}
+2 -2
View File
@@ -49,7 +49,7 @@ export default function RouterContainer() {
key={currentPage}
className={cn(
'flex-1 flex flex-col overflow-x-hidden overflow-y-auto',
'scrollbar-gutter-stable motion-reduce:transition-none',
'motion-reduce:transition-none',
animationClass,
)}
>
@@ -57,7 +57,7 @@ export default function RouterContainer() {
{currentFeature ? (
<LoadedPage key={currentPage} pageKey={currentPage} />
) : (
<div className="flex-1 flex flex-col items-center justify-center p-8 text-center animate-in fade-in duration-300">
<div className="flex-1 flex flex-col items-center justify-center p-8 text-center fade-in-300">
<div className="flex h-12 w-12 items-center justify-center rounded-xl bg-destructive/10 text-destructive mb-4">
<AlertTriangle className="h-6 w-6" />
</div>
+1 -2
View File
@@ -24,8 +24,7 @@ const SIZE_CLASSES = {
large: 'text-base h-11 px-4 py-2 rounded-lg',
} as const;
const SELECTED_CLASSES =
'bg-background text-foreground shadow-sm font-semibold animate-in fade-in-50 zoom-in-95 duration-150';
const SELECTED_CLASSES = 'bg-background text-foreground shadow-sm font-semibold fade-in-zoom-95';
const UNSELECTED_CLASSES = 'hover:bg-background/50 hover:text-foreground/80';
export default function SwitchButtonGroup<T extends string | number = string>({
+10 -4
View File
@@ -267,7 +267,13 @@ const TextInputArea = forwardRef<HTMLTextAreaElement, TextInputAreaProps>((props
<div className="flex items-center gap-1.5 ml-auto shrink-0">
{allowCopy && value && (
<CopyButton text={value} tooltip="复制内容" size="sm" className="h-7 w-7 p-1" />
<CopyButton
text={value}
tooltip="复制内容"
variant="ghost"
size="iconSm"
className="text-muted-foreground hover:text-foreground"
/>
)}
{showClear && value && !disabled && !readOnly && (
<Button
@@ -275,8 +281,8 @@ const TextInputArea = forwardRef<HTMLTextAreaElement, TextInputAreaProps>((props
onClick={handleClear}
aria-label="清空"
variant="ghost"
size="icon"
className="h-7 w-7 text-muted-foreground hover:text-destructive hover:bg-destructive/10"
size="iconSm"
className="text-muted-foreground hover:text-destructive hover:bg-destructive/10"
>
<X className="h-4 w-4" />
</Button>
@@ -287,7 +293,7 @@ const TextInputArea = forwardRef<HTMLTextAreaElement, TextInputAreaProps>((props
</div>
{displayError && (
<p className="text-xs font-medium text-destructive px-0.5 animate-in fade-in slide-in-from-top-1 duration-150">
<p className="text-xs font-medium text-destructive px-0.5 fade-in-slide-top-1">
{displayError}
</p>
)}
+1
View File
@@ -21,6 +21,7 @@ const buttonVariants = cva(
sm: 'h-9 rounded-md px-3',
lg: 'h-11 rounded-md px-8',
icon: 'h-10 w-10',
iconSm: 'h-7 w-7',
},
},
defaultVariants: {
+2 -2
View File
@@ -18,7 +18,7 @@ const DialogOverlay = React.forwardRef<
<DialogPrimitive.Overlay
ref={ref}
className={cn(
'fixed inset-0 z-50 bg-black/80 dark:bg-black/60 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',
'fixed inset-0 z-50 bg-black/80 dark:bg-black/60 transition-opacity duration-200 data-[state=closed]:opacity-0 data-[state=open]:opacity-100',
className,
)}
{...props}
@@ -41,7 +41,7 @@ const DialogContent = React.forwardRef<
<DialogPrimitive.Content
ref={ref}
className={cn(
'fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-white dark:bg-gray-900 p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg',
'fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-white dark:bg-gray-900 p-6 shadow-lg transition-all duration-200 data-[state=closed]:scale-95 data-[state=open]:scale-100 data-[state=closed]:opacity-0 data-[state=open]:opacity-100 sm:rounded-lg',
className,
)}
{...props}
+1 -1
View File
@@ -65,7 +65,7 @@ const SelectContent = React.forwardRef<
<SelectPrimitive.Content
ref={ref}
className={cn(
'relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
'relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md transition-all duration-200 data-[state=closed]:scale-95 data-[state=open]:scale-100 data-[state=closed]:opacity-0 data-[state=open]:opacity-100',
position === 'popper' &&
'data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1',
className,