fix settings dark theme styles
This commit is contained in:
1 parent
36df7c8c5d
commit
db9700aebd
4 files changed
+46
-44
No files matched your search
@@ -39,8 +39,10 @@ interface SettingsPaneProps {
|
||||
onShowGuide?: () => void;
|
||||
}
|
||||
|
||||
// Slate and brand color variables already switch values with the root theme.
|
||||
// Keep this pane on the base utilities so dark variants do not invert them twice.
|
||||
const SettingsGroup = ({ children }: { children: ReactNode }) => (
|
||||
<div className="min-w-0 divide-y divide-slate-200 overflow-hidden rounded-xl border border-slate-200 bg-white dark:divide-slate-800 dark:border-slate-800 dark:bg-slate-950 [&>*]:rounded-none [&>*]:border-0 [&>*]:bg-transparent [&>*]:dark:bg-transparent">
|
||||
<div className="min-w-0 divide-y divide-slate-200 overflow-hidden rounded-xl border border-slate-200 bg-white [&>*]:rounded-none [&>*]:border-0 [&>*]:bg-transparent">
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
@@ -79,10 +81,10 @@ export const SettingsPane = ({
|
||||
key: "general",
|
||||
label: t("settings.tabs.general"),
|
||||
icon: SlidersHorizontal,
|
||||
colorClass: "text-emerald-700 dark:text-emerald-400",
|
||||
bgColorClass: "bg-emerald-50/80 dark:bg-emerald-950/40",
|
||||
hoverColorClass: "hover:bg-emerald-50/40 dark:hover:bg-emerald-950/20",
|
||||
iconColorClass: "text-emerald-600 dark:text-emerald-400",
|
||||
colorClass: "text-emerald-700",
|
||||
bgColorClass: "bg-emerald-50/80",
|
||||
hoverColorClass: "hover:bg-emerald-50/40",
|
||||
iconColorClass: "text-emerald-600",
|
||||
},
|
||||
...(isOwner
|
||||
? [
|
||||
@@ -90,10 +92,10 @@ export const SettingsPane = ({
|
||||
key: "users" as const,
|
||||
label: t("users.title"),
|
||||
icon: Users,
|
||||
colorClass: "text-emerald-700 dark:text-emerald-400",
|
||||
bgColorClass: "bg-emerald-50/80 dark:bg-emerald-950/40",
|
||||
hoverColorClass: "hover:bg-emerald-50/40 dark:hover:bg-emerald-950/20",
|
||||
iconColorClass: "text-emerald-600 dark:text-emerald-400",
|
||||
colorClass: "text-emerald-700",
|
||||
bgColorClass: "bg-emerald-50/80",
|
||||
hoverColorClass: "hover:bg-emerald-50/40",
|
||||
iconColorClass: "text-emerald-600",
|
||||
},
|
||||
]
|
||||
: []),
|
||||
@@ -101,28 +103,28 @@ export const SettingsPane = ({
|
||||
key: "data",
|
||||
label: t("settings.tabs.data"),
|
||||
icon: Database,
|
||||
colorClass: "text-emerald-700 dark:text-emerald-400",
|
||||
bgColorClass: "bg-emerald-50/80 dark:bg-emerald-950/40",
|
||||
hoverColorClass: "hover:bg-emerald-50/40 dark:hover:bg-emerald-950/20",
|
||||
iconColorClass: "text-emerald-600 dark:text-emerald-400",
|
||||
colorClass: "text-emerald-700",
|
||||
bgColorClass: "bg-emerald-50/80",
|
||||
hoverColorClass: "hover:bg-emerald-50/40",
|
||||
iconColorClass: "text-emerald-600",
|
||||
},
|
||||
{
|
||||
key: "ai",
|
||||
label: t("settings.tabs.ai"),
|
||||
icon: Sparkles,
|
||||
colorClass: "text-emerald-700 dark:text-emerald-400",
|
||||
bgColorClass: "bg-emerald-50/80 dark:bg-emerald-950/40",
|
||||
hoverColorClass: "hover:bg-emerald-50/40 dark:hover:bg-emerald-950/20",
|
||||
iconColorClass: "text-emerald-600 dark:text-emerald-400",
|
||||
colorClass: "text-emerald-700",
|
||||
bgColorClass: "bg-emerald-50/80",
|
||||
hoverColorClass: "hover:bg-emerald-50/40",
|
||||
iconColorClass: "text-emerald-600",
|
||||
},
|
||||
{
|
||||
key: "account",
|
||||
label: t("settings.tabs.account"),
|
||||
icon: Shield,
|
||||
colorClass: "text-emerald-700 dark:text-emerald-400",
|
||||
bgColorClass: "bg-emerald-50/80 dark:bg-emerald-950/40",
|
||||
hoverColorClass: "hover:bg-emerald-50/40 dark:hover:bg-emerald-950/20",
|
||||
iconColorClass: "text-emerald-600 dark:text-emerald-400",
|
||||
colorClass: "text-emerald-700",
|
||||
bgColorClass: "bg-emerald-50/80",
|
||||
hoverColorClass: "hover:bg-emerald-50/40",
|
||||
iconColorClass: "text-emerald-600",
|
||||
},
|
||||
];
|
||||
|
||||
@@ -153,9 +155,9 @@ export const SettingsPane = ({
|
||||
const HeaderIconColorClass = (() => {
|
||||
if (activeMobileTab !== null) {
|
||||
const activeItem = tabItems.find((item) => item.key === activeMobileTab);
|
||||
return activeItem ? activeItem.iconColorClass : "text-emerald-700 dark:text-emerald-400";
|
||||
return activeItem ? activeItem.iconColorClass : "text-emerald-700";
|
||||
}
|
||||
return "text-emerald-700 dark:text-emerald-400";
|
||||
return "text-emerald-700";
|
||||
})();
|
||||
|
||||
const renderTabContent = (key: TabKey) => {
|
||||
@@ -205,8 +207,8 @@ export const SettingsPane = ({
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex h-full min-h-0 min-w-0 flex-col overflow-x-hidden bg-slate-50 dark:bg-slate-900/40">
|
||||
<header className="flex h-[calc(3.5rem+env(safe-area-inset-top))] shrink-0 items-end justify-between border-b border-slate-200 bg-white px-4 pb-3 pt-[env(safe-area-inset-top)] dark:border-slate-800 dark:bg-slate-950 lg:h-16 lg:items-center lg:px-6 lg:pb-0 lg:pt-0">
|
||||
<div className="flex h-full min-h-0 min-w-0 flex-col overflow-x-hidden bg-slate-50">
|
||||
<header className="flex h-[calc(3.5rem+env(safe-area-inset-top))] shrink-0 items-end justify-between border-b border-slate-200 bg-white px-4 pb-3 pt-[env(safe-area-inset-top)] lg:h-16 lg:items-center lg:px-6 lg:pb-0 lg:pt-0">
|
||||
<div className="flex min-w-0 items-center gap-3">
|
||||
<Button
|
||||
size="icon"
|
||||
@@ -214,21 +216,21 @@ export const SettingsPane = ({
|
||||
title={t("common.back")}
|
||||
aria-label={t("common.back")}
|
||||
onClick={handleBack}
|
||||
className="h-9 w-9 rounded-lg hover:bg-slate-100 dark:hover:bg-slate-900"
|
||||
className="h-9 w-9 rounded-lg hover:bg-slate-100"
|
||||
>
|
||||
<ChevronLeft className="h-5 w-5 text-slate-500" />
|
||||
</Button>
|
||||
<div className="min-w-0">
|
||||
<h1 className={`flex items-center gap-2 ${WORKSPACE_PAGE_TITLE_CLASSNAME}`}>
|
||||
<HeaderIcon className={cn("h-4 w-4 shrink-0 transition-colors", HeaderIconColorClass)} />
|
||||
<span className="truncate text-slate-900 dark:text-slate-100">{getHeaderTitle()}</span>
|
||||
<span className="truncate text-slate-900">{getHeaderTitle()}</span>
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
<ThemeToggle className="inline-flex" showLabel />
|
||||
</header>
|
||||
|
||||
<div className="flex flex-1 min-h-0 min-w-0 bg-slate-50/50 dark:bg-slate-900/20">
|
||||
<div className="flex flex-1 min-h-0 min-w-0 bg-slate-50/50">
|
||||
{/* 桌面端布局:双栏 */}
|
||||
<div className="hidden lg:flex flex-1 min-h-0 min-w-0 mx-auto max-w-5xl px-6 py-6 gap-6">
|
||||
{/* 左侧垂直 Tab 栏 */}
|
||||
@@ -245,10 +247,10 @@ export const SettingsPane = ({
|
||||
"flex items-center gap-3 px-3.5 py-2.5 rounded-xl text-sm font-semibold transition-all duration-150 text-left w-full",
|
||||
isSelected
|
||||
? `${item.colorClass} ${item.bgColorClass}`
|
||||
: "text-slate-600 hover:text-slate-900 dark:text-slate-400 dark:hover:text-slate-200 hover:bg-slate-200/50 dark:hover:bg-slate-800/50"
|
||||
: "text-slate-600 hover:bg-slate-200/50 hover:text-slate-900"
|
||||
)}
|
||||
>
|
||||
<Icon className={cn("h-4 w-4 shrink-0 transition-colors", isSelected ? item.colorClass : "text-slate-400 dark:text-slate-500")} />
|
||||
<Icon className={cn("h-4 w-4 shrink-0 transition-colors", isSelected ? item.colorClass : "text-slate-400")} />
|
||||
{item.label}
|
||||
</button>
|
||||
);
|
||||
@@ -268,7 +270,7 @@ export const SettingsPane = ({
|
||||
{activeMobileTab === null ? (
|
||||
/* 分类主菜单 */
|
||||
<div className="grid gap-2">
|
||||
<div className="divide-y divide-slate-100 overflow-hidden rounded-2xl border border-slate-200 bg-white dark:divide-slate-800 dark:border-slate-800 dark:bg-slate-950">
|
||||
<div className="divide-y divide-slate-100 overflow-hidden rounded-2xl border border-slate-200 bg-white">
|
||||
{tabItems.map((item) => {
|
||||
const Icon = item.icon;
|
||||
return (
|
||||
@@ -276,15 +278,15 @@ export const SettingsPane = ({
|
||||
key={item.key}
|
||||
type="button"
|
||||
onClick={() => setActiveMobileTab(item.key)}
|
||||
className="flex items-center justify-between gap-4 p-4 text-left hover:bg-slate-50/50 dark:hover:bg-slate-900/40 transition-colors w-full"
|
||||
className="flex w-full items-center justify-between gap-4 p-4 text-left transition-colors hover:bg-slate-50/50"
|
||||
>
|
||||
<div className="flex items-center gap-3">
|
||||
<div className={cn("flex h-8 w-8 items-center justify-center rounded-lg", item.bgColorClass)}>
|
||||
<Icon className={cn("h-4 w-4", item.iconColorClass)} />
|
||||
</div>
|
||||
<span className="text-sm font-semibold text-slate-800 dark:text-slate-200">{item.label}</span>
|
||||
<span className="text-sm font-semibold text-slate-800">{item.label}</span>
|
||||
</div>
|
||||
<ChevronRight className="h-4 w-4 text-slate-400 dark:text-slate-600" />
|
||||
<ChevronRight className="h-4 w-4 text-slate-400" />
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
|
||||
@@ -29,7 +29,7 @@ type OperationKind = "export" | "import";
|
||||
const Progress = ({ progress }: { progress: EdgeEverZipProgress }) => {
|
||||
const percentage = progress.total > 0 ? Math.round((progress.completed / progress.total) * 100) : 0;
|
||||
return (
|
||||
<div className="h-1.5 overflow-hidden rounded-full bg-slate-200 dark:bg-slate-800">
|
||||
<div className="h-1.5 overflow-hidden rounded-full bg-slate-200">
|
||||
<div className="h-full rounded-full bg-emerald-600 transition-[width]" style={{ width: `${percentage}%` }} />
|
||||
</div>
|
||||
);
|
||||
@@ -146,7 +146,7 @@ export const DataExportCard = () => {
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="grid gap-3 p-4 pt-0">
|
||||
<div className="grid gap-2 rounded-lg border border-slate-200 dark:border-slate-800 p-3 bg-white/40 dark:bg-slate-900/10 md:grid-cols-[minmax(0,1fr)_auto] md:items-center">
|
||||
<div className="grid gap-2 rounded-lg border border-slate-200 bg-card/40 p-3 md:grid-cols-[minmax(0,1fr)_auto] md:items-center">
|
||||
<div className="min-w-0">
|
||||
<CardDescription className="text-xs leading-5">{t("dataExport.description")}</CardDescription>
|
||||
</div>
|
||||
|
||||
@@ -125,7 +125,7 @@ export const SystemInfoCard = () => {
|
||||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
className="h-8 w-full bg-white dark:bg-slate-950 px-3 text-xs sm:w-auto"
|
||||
className="h-8 w-full bg-white px-3 text-xs sm:w-auto"
|
||||
type="button"
|
||||
onClick={() => void handleCopy()}
|
||||
>
|
||||
@@ -135,9 +135,9 @@ export const SystemInfoCard = () => {
|
||||
</div>
|
||||
<div className="grid gap-2 sm:grid-cols-2">
|
||||
{infoItems.map((item) => (
|
||||
<div key={item.label} className="min-w-0 rounded-lg border border-slate-200 dark:border-slate-800 bg-white dark:bg-slate-900/30 px-3 py-2.5">
|
||||
<div className="text-[11px] font-semibold uppercase text-slate-400 dark:text-slate-500">{item.label}</div>
|
||||
<div className="mt-1 truncate font-mono text-xs font-semibold text-slate-800 dark:text-slate-200" title={item.value}>
|
||||
<div key={item.label} className="min-w-0 rounded-lg border border-slate-200 bg-white px-3 py-2.5">
|
||||
<div className="text-[11px] font-semibold uppercase text-slate-400">{item.label}</div>
|
||||
<div className="mt-1 truncate font-mono text-xs font-semibold text-slate-800" title={item.value}>
|
||||
{item.value}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -87,17 +87,17 @@ export const UserManagementCard = () => {
|
||||
<CardContent className="grid gap-2 p-4 pt-0">
|
||||
{usersQuery.isLoading ? <p className="text-sm text-slate-500">{t("users.loading")}</p> : null}
|
||||
{usersQuery.data?.users.map((user) => (
|
||||
<div key={user.id} className="flex flex-wrap items-center justify-between gap-3 rounded-lg border border-slate-200 dark:border-slate-800 p-3 bg-white/40 dark:bg-slate-900/10">
|
||||
<div key={user.id} className="flex flex-wrap items-center justify-between gap-3 rounded-lg border border-slate-200 bg-card/40 p-3">
|
||||
<div className="min-w-0">
|
||||
<p className="truncate text-sm font-semibold text-slate-800 dark:text-slate-200">{user.displayName || user.username}</p>
|
||||
<p className="truncate text-xs text-slate-500 dark:text-slate-400">@{user.username} · {t(`users.roles.${user.role}`)}</p>
|
||||
<p className="truncate text-sm font-semibold text-slate-800">{user.displayName || user.username}</p>
|
||||
<p className="truncate text-xs text-slate-500">@{user.username} · {t(`users.roles.${user.role}`)}</p>
|
||||
</div>
|
||||
<div className="flex items-center gap-3">
|
||||
<Button size="sm" variant="outline" onClick={() => setResetUser(user)}>
|
||||
<KeyRound className="h-3.5 w-3.5" /> {t("users.resetPassword")}
|
||||
</Button>
|
||||
{user.role !== "owner" ? (
|
||||
<label className="flex items-center gap-2 text-xs text-slate-600 dark:text-slate-400">
|
||||
<label className="flex items-center gap-2 text-xs text-slate-600">
|
||||
{user.isDisabled ? t("users.disabled") : t("users.enabled")}
|
||||
<Switch
|
||||
checked={!user.isDisabled}
|
||||
|
||||
Reference in new issue
Block a user