feat: 初步适配主题颜色效果

This commit is contained in:
Montia37
2025-09-07 22:37:24 +08:00
parent b121bf13ac
commit eecdc179c3
23 changed files with 285 additions and 211 deletions

View File

@@ -2,8 +2,8 @@ import React from "react";
const Footer: React.FC = () => {
return (
<footer className="fixed inset-shadow-sm bottom-0 left-0 right-0 p-2 text-center purcarte-blur z-50">
<p className="flex justify-center text-sm text-second-foreground text-shadow-lg whitespace-pre">
<footer className="fixed inset-shadow-sm inset-shadow-(color:--accent-a4) bottom-0 left-0 right-0 p-2 text-center purcarte-blur z-50">
<p className="flex justify-center text-sm text-second-foreground text-shadow-lg text-shadow-(color:--accent-a4) whitespace-pre">
Powered by{" "}
<a
href="https://github.com/komari-monitor/komari"

View File

@@ -13,6 +13,7 @@ import { useEffect, useState } from "react";
import { useLocation } from "react-router-dom";
import { useIsMobile } from "@/hooks/useMobile";
import { useConfigItem } from "@/config";
import type { Appearance } from "@/hooks/useTheme";
import {
DropdownMenu,
DropdownMenuContent,
@@ -23,8 +24,8 @@ import {
interface HeaderProps {
viewMode: "grid" | "table";
setViewMode: (mode: "grid" | "table") => void;
theme: string;
toggleTheme: () => void;
appearance: Appearance;
setAppearance: (appearance: Appearance) => void;
searchTerm: string;
setSearchTerm: (term: string) => void;
}
@@ -32,8 +33,8 @@ interface HeaderProps {
export const Header = ({
viewMode,
setViewMode,
theme,
toggleTheme,
appearance,
setAppearance,
searchTerm,
setSearchTerm,
}: HeaderProps) => {
@@ -54,10 +55,15 @@ export const Header = ({
}
}, [sitename]);
const toggleAppearance = () => {
const newAppearance = appearance === "light" ? "dark" : "light";
setAppearance(newAppearance);
};
return (
<header className="purcarte-blur border-b border-border sticky top-0 flex items-center justify-center shadow-sm z-10">
<header className="purcarte-blur border-b border-(--accent-a4) sticky top-0 flex items-center justify-center shadow-sm shadow-(color:--accent-a4) z-10">
<div className="w-[90%] max-w-screen-2xl px-4 py-2 flex items-center justify-between">
<div className="flex items-center text-shadow-lg text-accent-foreground">
<div className="flex items-center text-shadow-lg text-shadow-(color:--accent-a4) text-accent-foreground">
<a href="/" className="flex items-center gap-2 text-2xl font-bold">
{enableLogo && logoUrl && (
<img src={logoUrl} alt="logo" className="h-8" />
@@ -79,13 +85,13 @@ export const Header = ({
className="relative group">
<Search className="size-5 text-primary" />
{searchTerm && (
<span className="absolute top-0 right-0 w-1.5 h-1.5 rounded-full bg-primary transform -translate-x-1/2"></span>
<span className="absolute top-0 right-0 w-1.5 h-1.5 rounded-full bg-(--accent-indicator) transform -translate-x-1/2"></span>
)}
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent
align="end"
className="purcarte-blur border-border rounded-xl w-48">
className="purcarte-blur border-(--accent-a4) rounded-xl w-48">
<div className="p-2">
<Input
type="search"
@@ -107,12 +113,12 @@ export const Header = ({
size="icon"
className="relative group">
<Menu className="size-5 text-primary transition-transform duration-300 group-data-[state=open]:rotate-180" />
<span className="absolute top-0 right-0 w-1.5 h-1.5 rounded-full bg-primary transform -translate-x-1/2 scale-0 transition-transform duration-300 group-data-[state=open]:scale-100"></span>
<span className="absolute top-0 right-0 w-1.5 h-1.5 rounded-full bg-(--accent-indicator) transform -translate-x-1/2 scale-0 transition-transform duration-300 group-data-[state=open]:scale-100"></span>
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent
align="end"
className="purcarte-blur border-border rounded-xl">
className="purcarte-blur border-(--accent-a4) rounded-xl">
<DropdownMenuItem
onClick={() =>
setViewMode(viewMode === "grid" ? "table" : "grid")
@@ -126,14 +132,14 @@ export const Header = ({
{viewMode === "grid" ? "表格视图" : "网格视图"}
</span>
</DropdownMenuItem>
<DropdownMenuItem onClick={toggleTheme}>
{theme === "dark" ? (
<DropdownMenuItem onClick={toggleAppearance}>
{appearance === "dark" ? (
<Sun className="size-4 mr-2 text-primary" />
) : (
<Moon className="size-4 mr-2 text-primary" />
)}
<span>
{theme === "dark" ? "浅色模式" : "深色模式"}
{appearance === "dark" ? "浅色模式" : "深色模式"}
</span>
</DropdownMenuItem>
{enableAdminButton && (
@@ -177,7 +183,7 @@ export const Header = ({
onClick={() => setIsSearchOpen(!isSearchOpen)}>
<Search className="size-5 text-primary" />
{searchTerm && (
<span className="absolute top-0 right-0 w-1.5 h-1.5 rounded-full bg-primary transform -translate-x-1/2"></span>
<span className="absolute top-0 right-0 w-1.5 h-1.5 rounded-full bg-(--accent-indicator) transform -translate-x-1/2"></span>
)}
</Button>
)}
@@ -193,8 +199,11 @@ export const Header = ({
<Grid3X3 className="size-5 text-primary" />
)}
</Button>
<Button variant="ghost" size="icon" onClick={toggleTheme}>
{theme === "dark" ? (
<Button
variant="ghost"
size="icon"
onClick={toggleAppearance}>
{appearance === "dark" ? (
<Sun className="size-5 text-primary" />
) : (
<Moon className="size-5 text-primary" />
@@ -226,14 +235,16 @@ export const Header = ({
</DropdownMenuTrigger>
<DropdownMenuContent
align="end"
className="animate-in slide-in-from-top-5 duration-300 purcarte-blur border-border rounded-xl">
<DropdownMenuItem onClick={toggleTheme}>
{theme === "dark" ? (
className="animate-in slide-in-from-top-5 duration-300 purcarte-blur border-(--accent-a4) rounded-xl">
<DropdownMenuItem onClick={toggleAppearance}>
{appearance === "dark" ? (
<Sun className="size-4 mr-2 text-primary" />
) : (
<Moon className="size-4 mr-2 text-primary" />
)}
<span>{theme === "dark" ? "浅色模式" : "深色模式"}</span>
<span>
{appearance === "dark" ? "浅色模式" : "深色模式"}
</span>
</DropdownMenuItem>
{enableAdminButton && (
<DropdownMenuItem asChild>
@@ -251,8 +262,11 @@ export const Header = ({
</DropdownMenu>
) : (
<>
<Button variant="ghost" size="icon" onClick={toggleTheme}>
{theme === "dark" ? (
<Button
variant="ghost"
size="icon"
onClick={toggleAppearance}>
{appearance === "dark" ? (
<Sun className="size-5 text-primary" />
) : (
<Moon className="size-5 text-primary" />

View File

@@ -58,7 +58,7 @@ export const NodeCard = ({ node, enableSwap }: NodeCardProps) => {
<div className="flex flex-wrap gap-1">
<Tag tags={tagList} />
</div>
<div className="border-t border-border/60 my-2"></div>
<div className="border-t border-(--accent-a4) my-2"></div>
<div className="flex items-center justify-around whitespace-nowrap">
<div className="flex items-center gap-1">
<CpuIcon className="size-4 text-blue-600 flex-shrink-0" />
@@ -113,7 +113,7 @@ export const NodeCard = ({ node, enableSwap }: NodeCardProps) => {
<span className="w-12 text-right">{diskUsage.toFixed(0)}%</span>
</div>
</div>
<div className="border-t border-border/60 my-2"></div>
<div className="border-t border-(--accent-a4) my-2"></div>
<div className="flex justify-between text-xs">
<span className="text-secondary-foreground"></span>
<div>
@@ -167,7 +167,7 @@ export const NodeCard = ({ node, enableSwap }: NodeCardProps) => {
{expired_at}
</span>
</div>
<div className="border-l border-border/60 mx-2"></div>
<div className="border-l border-(--accent-a4) mx-2"></div>
<div className="flex justify-end w-full">
<span className="text-secondary-foreground">
{isOnline && stats

View File

@@ -6,7 +6,7 @@ export const NodeListHeader = ({ enableSwap }: NodeListHeaderProps) => {
const gridCols = enableSwap ? "grid-cols-10" : "grid-cols-9";
return (
<div
className={`text-primary font-bold grid ${gridCols} text-center shadow-md gap-4 p-2 items-center rounded-lg bg-card transition-colors duration-200`}>
className={`text-primary font-bold grid ${gridCols} text-center shadow-sm shadow-(color:--accent-a4) gap-4 p-2 items-center rounded-lg bg-card transition-colors duration-200`}>
<div className="col-span-2"></div>
<div className="col-span-1">CPU</div>
<div className="col-span-1"></div>

View File

@@ -36,7 +36,7 @@ export const NodeListItem = ({
return (
<div
className={`grid ${gridCols} text-center shadow-md gap-4 p-2 text-nowrap items-center rounded-lg ${
className={`grid ${gridCols} text-center shadow-sm shadow-(color:--accent-a4) gap-4 p-2 text-nowrap items-center rounded-lg ${
isOnline
? ""
: "striped-bg-red-translucent-diagonal ring-2 ring-red-500/50"

View File

@@ -156,7 +156,7 @@ export const StatsBar = ({
}
};
return (
<div className="purcarte-blur min-w-[300px] rounded-lg text-secondary-foreground my-6 mx-4 px-4 box-border border border-border text-sm relative flex items-center min-h-[5rem]">
<div className="purcarte-blur min-w-[300px] rounded-lg text-secondary-foreground my-6 mx-4 px-4 box-border border border-(--accent-a4) text-sm relative flex items-center min-h-[5rem]">
<div className="absolute top-2 right-2">
<DropdownMenu modal={false}>
<DropdownMenuTrigger asChild>