fix: 修复输入框和按钮在暗色模式下的样式问题
- 为 :root 和 .dark 添加 color-scheme,使浏览器表单控件默认样式适配暗色模式 - 将 bg-primary 搭配 text-white 的按钮改为 text-primary-foreground - 替换残留的 hover:bg-blue-700、text-blue-500、bg-gray-200 等硬编码颜色 - 同步更新 TextInputArea 单元测试
This commit is contained in:
+10
-10
@@ -17,13 +17,13 @@ function DashboardCardSkeleton() {
|
|||||||
<div className="rounded-xl border border-border p-5 h-[100px]">
|
<div className="rounded-xl border border-border p-5 h-[100px]">
|
||||||
<div className="flex justify-between items-start">
|
<div className="flex justify-between items-start">
|
||||||
<div className="flex gap-3 items-center">
|
<div className="flex gap-3 items-center">
|
||||||
<div className="w-10 h-10 rounded-lg bg-gray-200 animate-pulse" />
|
<div className="w-10 h-10 rounded-lg bg-muted animate-pulse" />
|
||||||
<div>
|
<div>
|
||||||
<div className="w-24 h-5 bg-gray-200 rounded animate-pulse" />
|
<div className="w-24 h-5 bg-muted rounded animate-pulse" />
|
||||||
<div className="w-32 h-3.5 bg-gray-200 rounded animate-pulse mt-1.5" />
|
<div className="w-32 h-3.5 bg-muted rounded animate-pulse mt-1.5" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="w-3 h-3 rounded-full bg-gray-200 animate-pulse" />
|
<div className="w-3 h-3 rounded-full bg-muted animate-pulse" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -36,21 +36,21 @@ function ToolPageSkeleton() {
|
|||||||
return (
|
return (
|
||||||
<div className="p-5">
|
<div className="p-5">
|
||||||
{/* 标题区域 */}
|
{/* 标题区域 */}
|
||||||
<div className="w-44 h-7 bg-gray-200 rounded animate-pulse mb-4" />
|
<div className="w-44 h-7 bg-muted rounded animate-pulse mb-4" />
|
||||||
|
|
||||||
{/* 输入区域 */}
|
{/* 输入区域 */}
|
||||||
<div className="w-full h-[120px] bg-gray-200 rounded-xl animate-pulse mb-4" />
|
<div className="w-full h-[120px] bg-muted rounded-xl animate-pulse mb-4" />
|
||||||
|
|
||||||
{/* 控制栏 */}
|
{/* 控制栏 */}
|
||||||
<div className="flex gap-2 mb-4">
|
<div className="flex gap-2 mb-4">
|
||||||
<div className="w-24 h-9 bg-gray-200 rounded-lg animate-pulse" />
|
<div className="w-24 h-9 bg-muted rounded-lg animate-pulse" />
|
||||||
<div className="w-20 h-9 bg-gray-200 rounded-lg animate-pulse" />
|
<div className="w-20 h-9 bg-muted rounded-lg animate-pulse" />
|
||||||
<div className="flex-1" />
|
<div className="flex-1" />
|
||||||
<div className="w-22 h-9 bg-gray-200 rounded-lg animate-pulse" />
|
<div className="w-22 h-9 bg-muted rounded-lg animate-pulse" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 结果区域 */}
|
{/* 结果区域 */}
|
||||||
<div className="w-full h-[160px] bg-gray-200 rounded-xl animate-pulse" />
|
<div className="w-full h-[160px] bg-muted rounded-xl animate-pulse" />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -152,7 +152,7 @@ function ActionButton({
|
|||||||
typeof action.disabled === 'function' ? action.disabled(value) : action.disabled || !value;
|
typeof action.disabled === 'function' ? action.disabled(value) : action.disabled || !value;
|
||||||
|
|
||||||
const typeClasses: Record<string, string> = {
|
const typeClasses: Record<string, string> = {
|
||||||
primary: 'bg-primary text-white hover:bg-primary/90',
|
primary: 'bg-primary text-primary-foreground hover:bg-primary/90',
|
||||||
danger: 'text-red-600 hover:bg-red-500/10',
|
danger: 'text-red-600 hover:bg-red-500/10',
|
||||||
default: 'text-muted-foreground hover:bg-muted',
|
default: 'text-muted-foreground hover:bg-muted',
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -334,7 +334,7 @@ describe('TextInputArea 组件', () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const btn = screen.getByText('主要');
|
const btn = screen.getByText('主要');
|
||||||
expect(btn).toHaveClass('bg-primary', 'text-white');
|
expect(btn).toHaveClass('bg-primary', 'text-primary-foreground');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -195,7 +195,7 @@ export default function FileMode() {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
{isLoading ? (
|
{isLoading ? (
|
||||||
<div className="w-10 h-10 border-4 border-primary/30 border-t-blue-600 rounded-full animate-spin" />
|
<div className="w-10 h-10 border-4 border-primary/30 border-t-primary rounded-full animate-spin" />
|
||||||
) : info ? (
|
) : info ? (
|
||||||
<div className="flex flex-col items-center gap-1">
|
<div className="flex flex-col items-center gap-1">
|
||||||
<Upload className="w-10 h-10 text-primary" />
|
<Upload className="w-10 h-10 text-primary" />
|
||||||
|
|||||||
@@ -202,7 +202,7 @@ export default function ImageMode() {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
{isLoading ? (
|
{isLoading ? (
|
||||||
<div className="w-10 h-10 border-4 border-primary/30 border-t-blue-600 rounded-full animate-spin" />
|
<div className="w-10 h-10 border-4 border-primary/30 border-t-primary rounded-full animate-spin" />
|
||||||
) : info ? (
|
) : info ? (
|
||||||
<div className="flex flex-col items-center gap-1">
|
<div className="flex flex-col items-center gap-1">
|
||||||
{result && (
|
{result && (
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ export default function JsonFormatSection() {
|
|||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={sortKeys}
|
checked={sortKeys}
|
||||||
onChange={(e) => setSortKeys(e.target.checked)}
|
onChange={(e) => setSortKeys(e.target.checked)}
|
||||||
className="h-4 w-4 rounded border-input text-blue-500 focus:ring-primary"
|
className="h-4 w-4 rounded border-input text-primary focus:ring-primary"
|
||||||
/>
|
/>
|
||||||
<span className="text-xs font-bold">{t('jsonFormat:sortKeys')}</span>
|
<span className="text-xs font-bold">{t('jsonFormat:sortKeys')}</span>
|
||||||
</label>
|
</label>
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ export default function AutoRefreshToggle({ autoRefresh, onChange }: AutoRefresh
|
|||||||
onChange={(e) => onChange(e.target.checked)}
|
onChange={(e) => onChange(e.target.checked)}
|
||||||
className="sr-only peer"
|
className="sr-only peer"
|
||||||
/>
|
/>
|
||||||
<div className="w-9 h-5 bg-gray-200 peer-focus:outline-none peer-focus:ring-2 peer-focus:ring-amber-300 rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-background after:border-input after:border after:rounded-full after:h-4 after:w-4 after:transition-all peer-checked:bg-amber-500" />
|
<div className="w-9 h-5 bg-muted peer-focus:outline-none peer-focus:ring-2 peer-focus:ring-amber-300 rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-background after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-background after:border-input after:border after:rounded-full after:h-4 after:w-4 after:transition-all peer-checked:bg-amber-500" />
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ const LiveClock = React.memo(({ unit, onUseNow }: LiveClockProps) => {
|
|||||||
<button
|
<button
|
||||||
onClick={handleUseNow}
|
onClick={handleUseNow}
|
||||||
title={t('timestamp:useNowTooltip')}
|
title={t('timestamp:useNowTooltip')}
|
||||||
className="p-1.5 rounded-md bg-background text-primary shadow-sm hover:bg-blue-700 hover:text-white transition-colors"
|
className="p-1.5 rounded-md bg-background text-primary shadow-sm hover:bg-primary hover:text-primary-foreground transition-colors"
|
||||||
>
|
>
|
||||||
<Clock className="w-4 h-4" />
|
<Clock className="w-4 h-4" />
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ export default function Index() {
|
|||||||
{/* 立即转换 */}
|
{/* 立即转换 */}
|
||||||
<button
|
<button
|
||||||
onClick={convert}
|
onClick={convert}
|
||||||
className="block mx-auto mt-4 mb-1 max-w-[240px] w-full py-2.5 text-sm font-semibold rounded-lg bg-primary text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2 transition-all"
|
className="block mx-auto mt-4 mb-1 max-w-[240px] w-full py-2.5 text-sm font-semibold rounded-lg bg-primary text-primary-foreground hover:bg-primary/90 focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2 transition-all"
|
||||||
>
|
>
|
||||||
{t('timestamp:convertButton')}
|
{t('timestamp:convertButton')}
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
@layer base {
|
@layer base {
|
||||||
:root {
|
:root {
|
||||||
|
color-scheme: light;
|
||||||
--background: 0 0% 100%;
|
--background: 0 0% 100%;
|
||||||
--foreground: 222.2 84% 4.9%;
|
--foreground: 222.2 84% 4.9%;
|
||||||
|
|
||||||
@@ -36,6 +37,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.dark {
|
.dark {
|
||||||
|
color-scheme: dark;
|
||||||
--background: 222.2 84% 4.9%;
|
--background: 222.2 84% 4.9%;
|
||||||
--foreground: 210 40% 98%;
|
--foreground: 210 40% 98%;
|
||||||
|
|
||||||
@@ -74,4 +76,9 @@
|
|||||||
background-color: hsl(var(--background));
|
background-color: hsl(var(--background));
|
||||||
color: hsl(var(--foreground));
|
color: hsl(var(--foreground));
|
||||||
}
|
}
|
||||||
|
input,
|
||||||
|
textarea,
|
||||||
|
select {
|
||||||
|
color: hsl(var(--foreground));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user