mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-09-28 05:46:36 +08:00
style(frontend): remove hardcoded indigo colors in settings components
Replace all manual bg-indigo and text-indigo overrides with standard CSS variables such as bg-primary/10 and text-primary across common settings modules to support theme integration.
This commit is contained in:
@@ -85,7 +85,7 @@ export function AdminSettingsPageClient() {
|
||||
if (loading || !user || !user.is_admin) {
|
||||
return (
|
||||
<div className="flex items-center justify-center min-h-[400px]">
|
||||
<Loader2 className="size-6 animate-spin text-indigo-500" />
|
||||
<Loader2 className="size-6 animate-spin text-primary" />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -194,7 +194,7 @@ export function AccessTokenMain() {
|
||||
<CardContent className="pt-6 space-y-4">
|
||||
{accessTokensQuery.isPending ? (
|
||||
<div className="flex items-center justify-center py-8">
|
||||
<Loader2 className="size-6 animate-spin text-indigo-500" />
|
||||
<Loader2 className="size-6 animate-spin text-primary" />
|
||||
</div>
|
||||
) : (accessTokensQuery.data ?? []).length > 0 ? (
|
||||
<div className="space-y-3">
|
||||
@@ -231,7 +231,7 @@ export function AccessTokenMain() {
|
||||
type="button"
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="text-xs border-dashed text-muted-foreground hover:text-indigo-500 hover:bg-indigo-500/5 rounded-lg h-8 px-2.5"
|
||||
className="text-xs border-dashed text-muted-foreground hover:text-primary hover:bg-primary/5 rounded-lg h-8 px-2.5"
|
||||
onClick={() => handleCopyText(token.masked_token, token.id)}
|
||||
>
|
||||
{copiedId === token.id ? (
|
||||
@@ -245,7 +245,7 @@ export function AccessTokenMain() {
|
||||
type="button"
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="text-xs border-dashed text-muted-foreground hover:text-indigo-500 hover:bg-indigo-500/5 rounded-lg h-8 px-2.5"
|
||||
className="text-xs border-dashed text-muted-foreground hover:text-primary hover:bg-primary/5 rounded-lg h-8 px-2.5"
|
||||
onClick={() => handleRotateToken(token.id, token.name)}
|
||||
disabled={rotateTokenMutation.isPending}
|
||||
>
|
||||
@@ -305,7 +305,7 @@ export function AccessTokenMain() {
|
||||
value={tokenName}
|
||||
onChange={(e) => setTokenName(e.target.value)}
|
||||
disabled={createTokenMutation.isPending}
|
||||
className="rounded-xl border border-dashed focus:border-indigo-500 focus:ring-0 focus-visible:ring-0"
|
||||
className="rounded-xl border border-dashed focus:border-primary focus:ring-0 focus-visible:ring-0"
|
||||
/>
|
||||
</div>
|
||||
{user?.is_admin && (
|
||||
@@ -375,15 +375,15 @@ export function AccessTokenMain() {
|
||||
{newCreatedToken && (
|
||||
<div className="space-y-4 py-2">
|
||||
{/* 明文 Token 文本框 */}
|
||||
<div className="flex items-center gap-2 rounded-xl bg-indigo-500/5 border border-dashed border-indigo-500/30 p-3">
|
||||
<span className="font-mono text-xs select-all break-all flex-1 text-indigo-600 font-semibold leading-relaxed">
|
||||
<div className="flex items-center gap-2 rounded-xl bg-primary/5 border border-dashed border-primary/30 p-3">
|
||||
<span className="font-mono text-xs select-all break-all flex-1 text-primary font-semibold leading-relaxed">
|
||||
{newCreatedToken.token}
|
||||
</span>
|
||||
<Button
|
||||
type="button"
|
||||
size="icon"
|
||||
variant="outline"
|
||||
className="size-8 rounded-lg shrink-0 border-dashed text-indigo-500 hover:bg-indigo-500/10 hover:border-indigo-500/30 transition-colors"
|
||||
className="size-8 rounded-lg shrink-0 border-dashed text-primary hover:bg-primary/10 hover:border-primary/30 transition-colors"
|
||||
onClick={() => handleCopyText(newCreatedToken.token, 9999)}
|
||||
>
|
||||
{copiedId === 9999 ? (
|
||||
|
||||
@@ -88,7 +88,7 @@ export function OperationTab({ configs, systemConfigsQuery }: OperationTabProps)
|
||||
<Card className="border border-dashed shadow-sm">
|
||||
<CardHeader className="border-b border-dashed pb-4">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="p-1.5 rounded-lg bg-indigo-500/10 text-indigo-500">
|
||||
<div className="p-1.5 rounded-lg bg-primary/10 text-primary">
|
||||
<KeyRound className="size-4" />
|
||||
</div>
|
||||
<div>
|
||||
@@ -125,9 +125,9 @@ export function OperationTab({ configs, systemConfigsQuery }: OperationTabProps)
|
||||
</div>
|
||||
|
||||
{/* 当前白名单列表 */}
|
||||
<div className="rounded-xl border border-dashed p-4 bg-card hover:bg-muted/10 hover:border-indigo-500/30 transition-all duration-300 shadow-sm space-y-3">
|
||||
<div className="rounded-xl border border-dashed p-4 bg-card hover:bg-muted/10 hover:border-primary/30 transition-all duration-300 shadow-sm space-y-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<ShieldAlert className="size-4 text-indigo-500" />
|
||||
<ShieldAlert className="size-4 text-primary" />
|
||||
<span className="font-medium text-sm text-foreground">当前免鉴权列表</span>
|
||||
</div>
|
||||
|
||||
@@ -137,14 +137,14 @@ export function OperationTab({ configs, systemConfigsQuery }: OperationTabProps)
|
||||
<Badge
|
||||
key={type}
|
||||
variant="secondary"
|
||||
className="px-2.5 py-1 text-xs gap-1.5 flex items-center bg-indigo-500/10 text-indigo-700 dark:text-indigo-300 dark:bg-indigo-500/20 border border-indigo-500/20"
|
||||
className="px-2.5 py-1 text-xs gap-1.5 flex items-center bg-primary/10 text-primary dark:bg-primary/20 border border-primary/20"
|
||||
>
|
||||
{availableTypes.find(t => t.value === type)?.label || type}
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => handleRemoveType(type)}
|
||||
disabled={updateWhitelistMutation.isPending || systemConfigsQuery.isPending}
|
||||
className="rounded-full outline-hidden hover:bg-indigo-500/20 p-0.5 text-indigo-600 dark:text-indigo-400 cursor-pointer disabled:cursor-not-allowed"
|
||||
className="rounded-full outline-hidden hover:bg-primary/20 p-0.5 text-primary cursor-pointer disabled:cursor-not-allowed"
|
||||
>
|
||||
<X className="size-3" />
|
||||
</button>
|
||||
|
||||
@@ -112,7 +112,7 @@ export function OtherTab({ configs }: OtherTabProps) {
|
||||
<Card className="border border-dashed shadow-sm">
|
||||
<CardHeader className="border-b border-dashed pb-4">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="p-1.5 rounded-lg bg-indigo-500/10 text-indigo-500">
|
||||
<div className="p-1.5 rounded-lg bg-primary/10 text-primary">
|
||||
<LayoutList className="size-4" />
|
||||
</div>
|
||||
<div>
|
||||
@@ -141,11 +141,11 @@ export function OtherTab({ configs }: OtherTabProps) {
|
||||
return (
|
||||
<div
|
||||
key={item.path}
|
||||
className="flex items-center justify-between gap-4 rounded-xl border border-dashed p-4 bg-card hover:bg-muted/10 hover:border-indigo-500/30 transition-all duration-300 shadow-sm"
|
||||
className="flex items-center justify-between gap-4 rounded-xl border border-dashed p-4 bg-card hover:bg-muted/10 hover:border-primary/30 transition-all duration-300 shadow-sm"
|
||||
>
|
||||
<div className="space-y-1.5 flex-1 min-w-0 pr-2">
|
||||
<div className="flex items-center gap-2">
|
||||
{Icon && <Icon className="size-4 text-indigo-500 shrink-0" />}
|
||||
{Icon && <Icon className="size-4 text-primary shrink-0" />}
|
||||
<span className="font-medium text-sm text-foreground truncate">{item.label}</span>
|
||||
{isReadOnly && (
|
||||
<span className="text-[9px] px-1.5 py-0.5 rounded bg-muted text-muted-foreground border shrink-0">
|
||||
@@ -171,8 +171,8 @@ export function OtherTab({ configs }: OtherTabProps) {
|
||||
</div>
|
||||
))}
|
||||
|
||||
<div className="p-3.5 rounded-lg border border-dashed border-indigo-500/20 bg-indigo-500/5 flex items-start gap-2.5">
|
||||
<Info className="size-4 text-indigo-500 shrink-0 mt-0.5" />
|
||||
<div className="p-3.5 rounded-lg border border-dashed border-primary/20 bg-primary/5 flex items-start gap-2.5">
|
||||
<Info className="size-4 text-primary shrink-0 mt-0.5" />
|
||||
<div className="text-xs text-muted-foreground leading-relaxed">
|
||||
<span className="font-semibold text-foreground">安全提示:</span>
|
||||
为了防止管理员在关闭“系统设置”后导致无法重新访问此配置页,系统限制了“系统设置”的关闭权限。其它所有菜单均可自由开关,隐藏后对应的分组标题在为空时也会自动隐藏。
|
||||
|
||||
@@ -275,7 +275,7 @@ export function ProfileMain() {
|
||||
>
|
||||
<Avatar className="size-20 md:size-24 border-2 border-primary/10 shadow-md">
|
||||
<AvatarImage src={user.avatar_url} alt={user.nickname || user.username} />
|
||||
<AvatarFallback className="text-2xl bg-indigo-600 text-white font-bold">
|
||||
<AvatarFallback className="text-2xl bg-primary text-primary-foreground font-bold">
|
||||
{(user.nickname || user.username).slice(0, 2).toUpperCase()}
|
||||
</AvatarFallback>
|
||||
</Avatar>
|
||||
@@ -342,7 +342,7 @@ export function ProfileMain() {
|
||||
href={user.website.startsWith("http") ? user.website : `http://${user.website}`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-indigo-600 hover:underline"
|
||||
className="text-primary hover:underline"
|
||||
>
|
||||
{user.website}
|
||||
</a>
|
||||
@@ -473,7 +473,7 @@ export function ProfileMain() {
|
||||
<div className="space-y-6 bg-card border border-dashed rounded-lg p-6 flex flex-col justify-between">
|
||||
<div>
|
||||
<div className="border-b pb-4 flex items-center gap-2">
|
||||
<div className="p-1.5 rounded-lg bg-indigo-500/10 text-indigo-500">
|
||||
<div className="p-1.5 rounded-lg bg-primary/10 text-primary">
|
||||
<Link2 className="size-4" />
|
||||
</div>
|
||||
<div>
|
||||
@@ -487,7 +487,7 @@ export function ProfileMain() {
|
||||
<h3 className="text-[11px] font-semibold text-muted-foreground uppercase tracking-wider">已绑定账号</h3>
|
||||
{externalAccountBindingsQuery.isPending ? (
|
||||
<div className="flex items-center justify-center py-4">
|
||||
<Loader2 className="size-4 animate-spin text-indigo-500" />
|
||||
<Loader2 className="size-4 animate-spin text-primary" />
|
||||
</div>
|
||||
) : (externalAccountBindingsQuery.data ?? []).length > 0 ? (
|
||||
<div className="space-y-2">
|
||||
@@ -534,7 +534,7 @@ export function ProfileMain() {
|
||||
<h3 className="text-[11px] font-semibold text-muted-foreground uppercase tracking-wider">绑定新账号</h3>
|
||||
{publicAuthSourcesQuery.isPending ? (
|
||||
<div className="flex items-center justify-center py-4">
|
||||
<Loader2 className="size-4 animate-spin text-indigo-500" />
|
||||
<Loader2 className="size-4 animate-spin text-primary" />
|
||||
</div>
|
||||
) : (publicAuthSourcesQuery.data ?? []).length > 0 ? (
|
||||
<div className="grid grid-cols-1 gap-2">
|
||||
@@ -543,16 +543,16 @@ export function ProfileMain() {
|
||||
key={source.id}
|
||||
type="button"
|
||||
variant="outline"
|
||||
className="flex items-center justify-between w-full border border-dashed rounded-xl px-3 py-2 text-left font-normal text-xs hover:bg-indigo-500/5 hover:text-indigo-500 hover:border-indigo-500/30 transition-all duration-300 group h-8"
|
||||
className="flex items-center justify-between w-full border border-dashed rounded-xl px-3 py-2 text-left font-normal text-xs hover:bg-primary/5 hover:text-primary hover:border-primary/30 transition-all duration-300 group h-8"
|
||||
onClick={() => {
|
||||
void bindSourceMutation.mutateAsync(source.name)
|
||||
}}
|
||||
>
|
||||
<div className="flex items-center gap-1.5">
|
||||
<Link2 className="size-3 text-muted-foreground group-hover:text-indigo-500" />
|
||||
<Link2 className="size-3 text-muted-foreground group-hover:text-primary" />
|
||||
<span>绑定 {source.display_name || source.name}</span>
|
||||
</div>
|
||||
<ArrowRight className="size-3 opacity-0 -translate-x-1 group-hover:opacity-100 group-hover:translate-x-0 transition-all text-indigo-500" />
|
||||
<ArrowRight className="size-3 opacity-0 -translate-x-1 group-hover:opacity-100 group-hover:translate-x-0 transition-all text-primary" />
|
||||
</Button>
|
||||
))}
|
||||
</div>
|
||||
@@ -583,7 +583,7 @@ export function ProfileMain() {
|
||||
>
|
||||
<Avatar className="size-20 border-2 border-primary/5 shadow-md">
|
||||
<AvatarImage src={avatarUrl} alt={nickname} />
|
||||
<AvatarFallback className="text-xl bg-indigo-600 text-white font-bold">
|
||||
<AvatarFallback className="text-xl bg-primary text-primary-foreground font-bold">
|
||||
{(nickname || "U").slice(0, 2).toUpperCase()}
|
||||
</AvatarFallback>
|
||||
</Avatar>
|
||||
|
||||
@@ -245,7 +245,7 @@ export function SecurityTab({ configs, systemConfigsQuery }: SecurityTabProps) {
|
||||
<Card className="border border-dashed shadow-sm">
|
||||
<CardHeader className="border-b border-dashed pb-4">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="p-1.5 rounded-lg bg-indigo-500/10 text-indigo-500">
|
||||
<div className="p-1.5 rounded-lg bg-primary/10 text-primary">
|
||||
<Settings className="size-4" />
|
||||
</div>
|
||||
<div>
|
||||
@@ -263,11 +263,11 @@ export function SecurityTab({ configs, systemConfigsQuery }: SecurityTabProps) {
|
||||
return (
|
||||
<div
|
||||
key={item.key}
|
||||
className="flex items-center justify-between gap-4 rounded-xl border border-dashed p-4 bg-card hover:bg-muted/10 hover:border-indigo-500/30 transition-all duration-300 shadow-sm"
|
||||
className="flex items-center justify-between gap-4 rounded-xl border border-dashed p-4 bg-card hover:bg-muted/10 hover:border-primary/30 transition-all duration-300 shadow-sm"
|
||||
>
|
||||
<div className="space-y-1">
|
||||
<div className="flex items-center gap-2">
|
||||
{Icon && <Icon className="size-4 text-indigo-500" />}
|
||||
{Icon && <Icon className="size-4 text-primary" />}
|
||||
<span className="font-medium text-sm text-foreground">{item.title}</span>
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground leading-relaxed pr-2">{item.description}</p>
|
||||
@@ -283,11 +283,11 @@ export function SecurityTab({ configs, systemConfigsQuery }: SecurityTabProps) {
|
||||
|
||||
{/* 登录状态保持时间 (选择后立即更改) */}
|
||||
<div
|
||||
className="flex items-center justify-between gap-4 rounded-xl border border-dashed p-4 bg-card hover:bg-muted/10 hover:border-indigo-500/30 transition-all duration-300 shadow-sm md:col-span-2"
|
||||
className="flex items-center justify-between gap-4 rounded-xl border border-dashed p-4 bg-card hover:bg-muted/10 hover:border-primary/30 transition-all duration-300 shadow-sm md:col-span-2"
|
||||
>
|
||||
<div className="space-y-1 pr-4">
|
||||
<div className="flex items-center gap-2">
|
||||
<Clock className="size-4 text-indigo-500" />
|
||||
<Clock className="size-4 text-primary" />
|
||||
<span className="font-medium text-sm text-foreground">登录状态保持时间</span>
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground leading-relaxed pr-2">
|
||||
@@ -340,7 +340,7 @@ export function SecurityTab({ configs, systemConfigsQuery }: SecurityTabProps) {
|
||||
<Card className="border border-dashed shadow-sm">
|
||||
<CardHeader className="border-b border-dashed pb-4 flex flex-row items-center justify-between gap-4">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="p-1.5 rounded-lg bg-indigo-500/10 text-indigo-500">
|
||||
<div className="p-1.5 rounded-lg bg-primary/10 text-primary">
|
||||
<Globe className="size-4" />
|
||||
</div>
|
||||
<div>
|
||||
@@ -390,7 +390,7 @@ export function SecurityTab({ configs, systemConfigsQuery }: SecurityTabProps) {
|
||||
<div className="flex items-center gap-4">
|
||||
<span className={`text-xs px-2.5 py-1 rounded-lg border font-medium hidden sm:inline-block ${
|
||||
source.client_secret_configured
|
||||
? "bg-indigo-500/5 text-indigo-500 border-indigo-500/10"
|
||||
? "bg-primary/5 text-primary border-primary/10"
|
||||
: "bg-rose-500/5 text-rose-500 border-rose-500/10"
|
||||
}`}>
|
||||
{source.client_secret_configured ? "Secret 已配置" : "Secret 未配置"}
|
||||
@@ -407,7 +407,7 @@ export function SecurityTab({ configs, systemConfigsQuery }: SecurityTabProps) {
|
||||
type="button"
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="size-8 text-muted-foreground hover:text-indigo-500 hover:bg-indigo-500/10 rounded-lg transition-colors"
|
||||
className="size-8 text-muted-foreground hover:text-primary hover:bg-primary/10 rounded-lg transition-colors"
|
||||
onClick={() => {
|
||||
setSelectedSource(source)
|
||||
setAuthSourceModalOpen(true)
|
||||
@@ -458,7 +458,7 @@ export function SecurityTab({ configs, systemConfigsQuery }: SecurityTabProps) {
|
||||
<Card className="border border-dashed shadow-sm">
|
||||
<CardHeader className="border-b border-dashed pb-4 flex flex-row items-center justify-between gap-4">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="p-1.5 rounded-lg bg-indigo-500/10 text-indigo-500">
|
||||
<div className="p-1.5 rounded-lg bg-primary/10 text-primary">
|
||||
<Shield className="size-4" />
|
||||
</div>
|
||||
<div>
|
||||
|
||||
@@ -193,7 +193,7 @@ export function SystemTab({ configs, systemConfigsQuery }: SystemTabProps) {
|
||||
<Card className="border border-dashed shadow-sm">
|
||||
<CardHeader className="border-b border-dashed pb-4">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="rounded-lg bg-indigo-500/10 p-1.5 text-indigo-500">
|
||||
<div className="rounded-lg bg-primary/10 p-1.5 text-primary">
|
||||
<Server className="size-4" />
|
||||
</div>
|
||||
<div>
|
||||
@@ -310,7 +310,7 @@ export function SystemTab({ configs, systemConfigsQuery }: SystemTabProps) {
|
||||
<Card className="border border-dashed shadow-sm">
|
||||
<CardHeader className="border-b border-dashed pb-4">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="p-1.5 rounded-lg bg-indigo-500/10 text-indigo-500">
|
||||
<div className="p-1.5 rounded-lg bg-primary/10 text-primary">
|
||||
<Mail className="size-4" />
|
||||
</div>
|
||||
<div>
|
||||
|
||||
@@ -124,7 +124,7 @@ export function TemplatesManager() {
|
||||
<Card className="border border-dashed shadow-sm">
|
||||
<CardHeader className="border-b border-dashed pb-4 flex flex-row items-center justify-between gap-4">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="p-1.5 rounded-lg bg-indigo-500/10 text-indigo-500">
|
||||
<div className="p-1.5 rounded-lg bg-primary/10 text-primary">
|
||||
<FileText className="size-4" />
|
||||
</div>
|
||||
<div>
|
||||
@@ -154,14 +154,14 @@ export function TemplatesManager() {
|
||||
{(templatesQuery.data ?? []).map((tmpl) => (
|
||||
<div
|
||||
key={tmpl.id}
|
||||
className="flex flex-col sm:flex-row sm:items-center justify-between gap-4 rounded-xl border border-dashed p-4 bg-card hover:bg-muted/10 hover:border-indigo-500/30 transition-all duration-300 shadow-sm"
|
||||
className="flex flex-col sm:flex-row sm:items-center justify-between gap-4 rounded-xl border border-dashed p-4 bg-card hover:bg-muted/10 hover:border-primary/30 transition-all duration-300 shadow-sm"
|
||||
>
|
||||
<div className="space-y-1.5">
|
||||
<div className="flex items-center gap-2 flex-wrap">
|
||||
<span className="font-semibold text-sm text-foreground">{tmpl.name}</span>
|
||||
<span className={`text-[10px] px-2 py-0.5 rounded-full border font-medium ${
|
||||
tmpl.is_system
|
||||
? "bg-indigo-500/10 text-indigo-500 border-indigo-500/20"
|
||||
? "bg-primary/10 text-primary border-primary/20"
|
||||
: "bg-amber-500/10 text-amber-500 border-amber-500/20"
|
||||
}`}>
|
||||
{tmpl.is_system ? "系统内置" : "自定义"}
|
||||
@@ -171,7 +171,7 @@ export function TemplatesManager() {
|
||||
</span>
|
||||
</div>
|
||||
<div className="text-xs text-muted-foreground">
|
||||
标识符: <span className="font-mono text-indigo-500 bg-indigo-500/5 px-1.5 py-0.5 rounded">{tmpl.key}</span>
|
||||
标识符: <span className="font-mono text-primary bg-primary/5 px-1.5 py-0.5 rounded">{tmpl.key}</span>
|
||||
{tmpl.subject && ` · 主题: ${tmpl.subject}`}
|
||||
</div>
|
||||
{tmpl.description && (
|
||||
@@ -185,7 +185,7 @@ export function TemplatesManager() {
|
||||
type="button"
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="size-8 text-muted-foreground hover:text-indigo-500 hover:bg-indigo-500/10 rounded-lg transition-colors"
|
||||
className="size-8 text-muted-foreground hover:text-primary hover:bg-primary/10 rounded-lg transition-colors"
|
||||
onClick={() => handleOpenEdit(tmpl)}
|
||||
>
|
||||
<Pencil className="size-4" />
|
||||
|
||||
Reference in New Issue
Block a user