fix: 修复暗黑模式样式兼容性
- 在 tailwind.config.js 中启用 darkMode: 'class' 并扩展语义化颜色变量 - 将全项目硬编码颜色(bg-white、text-gray-*、border-gray-* 等)替换为语义化类名 - 修复 popup/index.html 硬编码浅色背景色 - 同步更新相关单元测试中的类名断言
This commit is contained in:
@@ -14,14 +14,14 @@ export default function DiffNavigator({ total, currentIndex, onPrev, onNext }: D
|
||||
|
||||
if (total === 0) {
|
||||
return (
|
||||
<div className="flex items-center justify-center gap-3 p-2.5 rounded-lg bg-blue-50 border border-blue-200">
|
||||
<span className="text-sm font-bold text-gray-500">{t('jsonDiff:noDiffs')}</span>
|
||||
<div className="flex items-center justify-center gap-3 p-2.5 rounded-lg bg-primary/10 border border-primary/30">
|
||||
<span className="text-sm font-bold text-muted-foreground">{t('jsonDiff:noDiffs')}</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex items-center justify-center gap-3 p-2.5 rounded-lg bg-blue-50 border border-blue-200">
|
||||
<div className="flex items-center justify-center gap-3 p-2.5 rounded-lg bg-primary/10 border border-primary/30">
|
||||
<button
|
||||
type="button"
|
||||
aria-label={t('jsonDiff:previousDiff')}
|
||||
|
||||
@@ -27,14 +27,14 @@ export default function DiffResult({ result, viewMode, activePath }: DiffResultP
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="p-3 rounded-lg bg-white border border-gray-200 font-mono text-sm overflow-x-auto min-h-[200px] max-h-[480px] overflow-y-auto">
|
||||
<div className="p-3 rounded-lg bg-background border border-border font-mono text-sm overflow-x-auto min-h-[200px] max-h-[480px] overflow-y-auto">
|
||||
<UnifiedView node={result.root} depth={0} activePath={activePath} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const SectionLabel = ({ text }: { text: string }) => (
|
||||
<span className="block mb-1.5 text-[11px] font-extrabold tracking-wider text-gray-500 uppercase">
|
||||
<span className="block mb-1.5 text-[11px] font-extrabold tracking-wider text-muted-foreground uppercase">
|
||||
{text}
|
||||
</span>
|
||||
);
|
||||
@@ -61,7 +61,7 @@ const colorForType = (type: DiffType): string => {
|
||||
if (type === 'added') return 'text-green-600';
|
||||
if (type === 'removed') return 'text-red-600';
|
||||
if (type === 'modified') return 'text-amber-600';
|
||||
return 'text-gray-900';
|
||||
return 'text-foreground';
|
||||
};
|
||||
|
||||
const bgForType = (type: DiffType): string | undefined => {
|
||||
|
||||
@@ -120,17 +120,17 @@ export default function JsonConvertSection({
|
||||
|
||||
{/* 转换结果 */}
|
||||
{result && result.output ? (
|
||||
<div className="relative rounded-lg bg-white border border-gray-200 overflow-hidden">
|
||||
<div className="relative rounded-lg bg-background border border-border overflow-hidden">
|
||||
{/* 结果头部 */}
|
||||
<div className="flex justify-between items-center px-4 py-2 border-b border-gray-200 bg-gray-50">
|
||||
<div className="flex justify-between items-center px-4 py-2 border-b border-border bg-muted">
|
||||
<div className="flex gap-4 items-center">
|
||||
<span className="text-[11px] font-extrabold text-gray-500">
|
||||
<span className="text-[11px] font-extrabold text-muted-foreground">
|
||||
{t(`jsonFormat:${pk}OutputLabel`)}
|
||||
</span>
|
||||
<span className="text-[10px] text-gray-400">
|
||||
<span className="text-[10px] text-muted-foreground">
|
||||
{t('jsonFormat:originalSize')}: {formatByteSize(result.originalBytes)}
|
||||
</span>
|
||||
<span className="text-[10px] text-gray-400">
|
||||
<span className="text-[10px] text-muted-foreground">
|
||||
{t('jsonFormat:formattedSize')}: {formatByteSize(result.outputBytes)}
|
||||
</span>
|
||||
</div>
|
||||
@@ -143,8 +143,10 @@ export default function JsonConvertSection({
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="p-4 rounded-lg bg-gray-50 border border-dashed border-gray-300 text-center">
|
||||
<p className="text-sm font-semibold text-gray-500">{t(`jsonFormat:${pk}EmptyHint`)}</p>
|
||||
<div className="p-4 rounded-lg bg-muted border border-dashed border-input text-center">
|
||||
<p className="text-sm font-semibold text-muted-foreground">
|
||||
{t(`jsonFormat:${pk}EmptyHint`)}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -17,7 +17,7 @@ export default function JsonDiffInput({
|
||||
}: JsonDiffInputProps) {
|
||||
return (
|
||||
<div className="flex-1 min-w-0">
|
||||
<span className="block mb-1.5 text-[11px] font-extrabold tracking-wider text-gray-500 uppercase">
|
||||
<span className="block mb-1.5 text-[11px] font-extrabold tracking-wider text-muted-foreground uppercase">
|
||||
{label}
|
||||
</span>
|
||||
<TextInputArea
|
||||
|
||||
@@ -73,7 +73,7 @@ export default function JsonFormatSection() {
|
||||
<div className="flex flex-col sm:flex-row gap-3 justify-between items-stretch sm:items-center">
|
||||
<div className="flex gap-3 items-center">
|
||||
{/* 缩进选择 */}
|
||||
<span className="text-[11px] font-extrabold text-gray-500">
|
||||
<span className="text-[11px] font-extrabold text-muted-foreground">
|
||||
{t('jsonFormat:indentSize')}
|
||||
</span>
|
||||
<SwitchButtonGroup
|
||||
@@ -90,7 +90,7 @@ export default function JsonFormatSection() {
|
||||
type="checkbox"
|
||||
checked={sortKeys}
|
||||
onChange={(e) => setSortKeys(e.target.checked)}
|
||||
className="h-4 w-4 rounded border-gray-300 text-blue-500 focus:ring-blue-500"
|
||||
className="h-4 w-4 rounded border-input text-blue-500 focus:ring-primary"
|
||||
/>
|
||||
<span className="text-xs font-bold">{t('jsonFormat:sortKeys')}</span>
|
||||
</label>
|
||||
@@ -119,8 +119,8 @@ export default function JsonFormatSection() {
|
||||
onChange={(e) => setInput(e.target.value)}
|
||||
rows={6}
|
||||
className={`w-full rounded-lg border ${
|
||||
error ? 'border-red-300' : 'border-gray-200'
|
||||
} p-3 font-mono text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 resize-y`}
|
||||
error ? 'border-red-300' : 'border-border'
|
||||
} p-3 font-mono text-sm focus:outline-none focus:ring-2 focus:ring-primary resize-y`}
|
||||
/>
|
||||
{error && (
|
||||
<p className="mx-3 mt-1 text-xs font-semibold text-red-500">
|
||||
@@ -131,17 +131,17 @@ export default function JsonFormatSection() {
|
||||
|
||||
{/* 格式化结果 */}
|
||||
{result && result.formatted ? (
|
||||
<div className="relative rounded-lg bg-white border border-gray-200 overflow-hidden">
|
||||
<div className="relative rounded-lg bg-background border border-border overflow-hidden">
|
||||
{/* 结果头部 */}
|
||||
<div className="flex justify-between items-center px-4 py-2 border-b border-gray-200 bg-gray-50">
|
||||
<div className="flex justify-between items-center px-4 py-2 border-b border-border bg-muted">
|
||||
<div className="flex gap-4 items-center">
|
||||
<span className="text-[11px] font-extrabold text-gray-500">
|
||||
<span className="text-[11px] font-extrabold text-muted-foreground">
|
||||
{t('jsonFormat:outputLabel')}
|
||||
</span>
|
||||
<span className="text-[10px] text-gray-400">
|
||||
<span className="text-[10px] text-muted-foreground">
|
||||
{t('jsonFormat:originalSize')}: {formatByteSize(result.originalBytes)}
|
||||
</span>
|
||||
<span className="text-[10px] text-gray-400">
|
||||
<span className="text-[10px] text-muted-foreground">
|
||||
{t('jsonFormat:formattedSize')}: {formatByteSize(result.formattedBytes)}
|
||||
</span>
|
||||
</div>
|
||||
@@ -154,8 +154,8 @@ export default function JsonFormatSection() {
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="p-4 rounded-lg bg-gray-50 border border-dashed border-gray-300 text-center">
|
||||
<p className="text-sm font-semibold text-gray-500">{t('jsonFormat:emptyHint')}</p>
|
||||
<div className="p-4 rounded-lg bg-muted border border-dashed border-input text-center">
|
||||
<p className="text-sm font-semibold text-muted-foreground">{t('jsonFormat:emptyHint')}</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -121,17 +121,17 @@ const NodeRow = ({
|
||||
onClick={() => setOverride(expanded ? 'closed' : 'open')}
|
||||
className={`cursor-pointer pr-1 py-0.5 ${bg ?? ''} ${
|
||||
isActive ? 'ring-2 ring-blue-500 rounded' : ''
|
||||
} flex items-center gap-1 whitespace-nowrap hover:${bg ? 'bg-opacity-80' : 'bg-gray-50'}`}
|
||||
} flex items-center gap-1 whitespace-nowrap hover:${bg ? 'bg-opacity-80' : 'bg-muted'}`}
|
||||
style={{ paddingLeft: `${depth * 1.5}rem` }}
|
||||
>
|
||||
<span className="w-3 text-gray-500 text-[11px]">{expanded ? '▾' : '▸'}</span>
|
||||
<span className="w-3 text-muted-foreground text-[11px]">{expanded ? '▾' : '▸'}</span>
|
||||
{!isRoot && (
|
||||
<span className="text-gray-900 font-bold">{isArrayKeyDisplay(node.key)}:</span>
|
||||
<span className="text-foreground font-bold">{isArrayKeyDisplay(node.key)}:</span>
|
||||
)}
|
||||
<span className="text-gray-500">{open}</span>
|
||||
{!expanded && <span className="text-gray-400 italic">{summarize(value)}</span>}
|
||||
<span className="text-muted-foreground">{open}</span>
|
||||
{!expanded && <span className="text-muted-foreground italic">{summarize(value)}</span>}
|
||||
{!expanded && (
|
||||
<span className="text-gray-500">
|
||||
<span className="text-muted-foreground">
|
||||
{close}
|
||||
{isLastChild ? '' : ','}
|
||||
</span>
|
||||
@@ -154,7 +154,7 @@ const NodeRow = ({
|
||||
)}
|
||||
{expanded && (
|
||||
<div
|
||||
className="text-gray-500 whitespace-nowrap"
|
||||
className="text-muted-foreground whitespace-nowrap"
|
||||
style={{ paddingLeft: `${depth * 1.5 + 1.0625}rem` }}
|
||||
>
|
||||
{close}
|
||||
@@ -175,8 +175,8 @@ const NodeRow = ({
|
||||
style={{ paddingLeft: `${depth * 1.5}rem` }}
|
||||
>
|
||||
<span className="w-3" />
|
||||
{!isRoot && <span className="text-gray-900 font-bold">{isArrayKeyDisplay(node.key)}:</span>}
|
||||
<span className={valueColor ?? 'text-gray-900'}>
|
||||
{!isRoot && <span className="text-foreground font-bold">{isArrayKeyDisplay(node.key)}:</span>}
|
||||
<span className={valueColor ?? 'text-foreground'}>
|
||||
{formatPrimitive(value)}
|
||||
{isLastChild ? '' : ','}
|
||||
</span>
|
||||
@@ -206,7 +206,7 @@ export default function JsonTree({
|
||||
}: JsonTreeProps) {
|
||||
const sideKey = useMemo(() => side, [side]);
|
||||
return (
|
||||
<div className="p-3 rounded-lg bg-white border border-gray-200 font-mono text-sm overflow-x-auto min-h-[200px] max-h-[480px] overflow-y-auto">
|
||||
<div className="p-3 rounded-lg bg-background border border-border font-mono text-sm overflow-x-auto min-h-[200px] max-h-[480px] overflow-y-auto">
|
||||
<NodeRow
|
||||
node={node}
|
||||
side={sideKey}
|
||||
|
||||
@@ -219,8 +219,10 @@ export default function Index() {
|
||||
<DiffResult result={diffResult} viewMode={viewMode} activePath={activePath} />
|
||||
</>
|
||||
) : (
|
||||
<div className="p-4 rounded-lg bg-gray-50 border border-dashed border-gray-300 text-center">
|
||||
<p className="text-sm font-semibold text-gray-500">{t('jsonDiff:emptyHint')}</p>
|
||||
<div className="p-4 rounded-lg bg-muted border border-dashed border-input text-center">
|
||||
<p className="text-sm font-semibold text-muted-foreground">
|
||||
{t('jsonDiff:emptyHint')}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
|
||||
Reference in New Issue
Block a user