feat: add plain palette option and update related components and styles
This commit is contained in:
@@ -49,6 +49,40 @@
|
||||
|
||||
:root {
|
||||
--radius: 0.65rem;
|
||||
--background: oklch(0.985 0 0);
|
||||
--foreground: oklch(0.205 0 0);
|
||||
--card: oklch(1 0 0);
|
||||
--card-foreground: oklch(0.205 0 0);
|
||||
--popover: oklch(1 0 0);
|
||||
--popover-foreground: oklch(0.205 0 0);
|
||||
--primary: oklch(0.32 0 0);
|
||||
--primary-foreground: oklch(0.985 0 0);
|
||||
--secondary: oklch(0.96 0 0);
|
||||
--secondary-foreground: oklch(0.24 0 0);
|
||||
--muted: oklch(0.96 0 0);
|
||||
--muted-foreground: oklch(0.48 0 0);
|
||||
--accent: oklch(0.94 0 0);
|
||||
--accent-foreground: oklch(0.24 0 0);
|
||||
--destructive: oklch(0.59 0.225 25);
|
||||
--border: oklch(0.89 0 0);
|
||||
--input: oklch(0.89 0 0);
|
||||
--ring: oklch(0.56 0 0);
|
||||
--chart-1: oklch(0.44 0 0);
|
||||
--chart-2: oklch(0.56 0 0);
|
||||
--chart-3: oklch(0.68 0 0);
|
||||
--chart-4: oklch(0.76 0 0);
|
||||
--chart-5: oklch(0.84 0 0);
|
||||
--sidebar: oklch(0.96 0 0);
|
||||
--sidebar-foreground: oklch(0.24 0 0);
|
||||
--sidebar-primary: oklch(0.32 0 0);
|
||||
--sidebar-primary-foreground: oklch(0.985 0 0);
|
||||
--sidebar-accent: oklch(0.92 0 0);
|
||||
--sidebar-accent-foreground: oklch(0.24 0 0);
|
||||
--sidebar-border: oklch(0.87 0 0);
|
||||
--sidebar-ring: oklch(0.56 0 0);
|
||||
}
|
||||
|
||||
:root[data-palette="green"] {
|
||||
--background: oklch(0.973 0.011 112);
|
||||
--foreground: oklch(0.22 0.021 210);
|
||||
--card: oklch(0.996 0.004 105);
|
||||
@@ -151,6 +185,40 @@
|
||||
}
|
||||
|
||||
.dark {
|
||||
--background: oklch(0.18 0 0);
|
||||
--foreground: oklch(0.94 0 0);
|
||||
--card: oklch(0.225 0 0);
|
||||
--card-foreground: oklch(0.94 0 0);
|
||||
--popover: oklch(0.225 0 0);
|
||||
--popover-foreground: oklch(0.94 0 0);
|
||||
--primary: oklch(0.82 0 0);
|
||||
--primary-foreground: oklch(0.18 0 0);
|
||||
--secondary: oklch(0.285 0 0);
|
||||
--secondary-foreground: oklch(0.94 0 0);
|
||||
--muted: oklch(0.285 0 0);
|
||||
--muted-foreground: oklch(0.7 0 0);
|
||||
--accent: oklch(0.32 0 0);
|
||||
--accent-foreground: oklch(0.94 0 0);
|
||||
--destructive: oklch(0.68 0.19 25);
|
||||
--border: oklch(1 0 0 / 10%);
|
||||
--input: oklch(1 0 0 / 14%);
|
||||
--ring: oklch(0.62 0 0);
|
||||
--chart-1: oklch(0.82 0 0);
|
||||
--chart-2: oklch(0.72 0 0);
|
||||
--chart-3: oklch(0.62 0 0);
|
||||
--chart-4: oklch(0.52 0 0);
|
||||
--chart-5: oklch(0.42 0 0);
|
||||
--sidebar: oklch(0.16 0 0);
|
||||
--sidebar-foreground: oklch(0.93 0 0);
|
||||
--sidebar-primary: oklch(0.82 0 0);
|
||||
--sidebar-primary-foreground: oklch(0.18 0 0);
|
||||
--sidebar-accent: oklch(0.27 0 0);
|
||||
--sidebar-accent-foreground: oklch(0.94 0 0);
|
||||
--sidebar-border: oklch(1 0 0 / 9%);
|
||||
--sidebar-ring: oklch(0.62 0 0);
|
||||
}
|
||||
|
||||
.dark[data-palette="green"] {
|
||||
--background: oklch(0.18 0.016 190);
|
||||
--foreground: oklch(0.94 0.009 155);
|
||||
--card: oklch(0.225 0.018 190);
|
||||
|
||||
+2
-2
@@ -26,9 +26,9 @@ const geistMono = Geist_Mono({
|
||||
const paletteScript = `
|
||||
try {
|
||||
var palette = window.localStorage.getItem("dashboard_palette");
|
||||
document.documentElement.dataset.palette = palette === "blue" || palette === "gray" ? palette : "green";
|
||||
document.documentElement.dataset.palette = palette === "plain" || palette === "blue" || palette === "green" || palette === "gray" ? palette : "plain";
|
||||
} catch (_) {
|
||||
document.documentElement.dataset.palette = "green";
|
||||
document.documentElement.dataset.palette = "plain";
|
||||
}
|
||||
`
|
||||
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
import assert from "node:assert/strict"
|
||||
import { readFile } from "node:fs/promises"
|
||||
import test from "node:test"
|
||||
|
||||
const paletteSource = await readFile(
|
||||
new URL("./palette-toggle.tsx", import.meta.url),
|
||||
"utf8",
|
||||
)
|
||||
const layoutSource = await readFile(new URL("../app/layout.tsx", import.meta.url), "utf8")
|
||||
const zhMessages = JSON.parse(
|
||||
await readFile(new URL("../messages/zh-CN.json", import.meta.url), "utf8"),
|
||||
)
|
||||
const enMessages = JSON.parse(
|
||||
await readFile(new URL("../messages/en-US.json", import.meta.url), "utf8"),
|
||||
)
|
||||
|
||||
test("plain palette is the default dashboard palette", () => {
|
||||
assert.match(paletteSource, /type PaletteMode = "plain" \| "blue" \| "green" \| "gray"/)
|
||||
assert.match(paletteSource, /const DEFAULT_PALETTE: PaletteMode = "plain"/)
|
||||
assert.match(layoutSource, /palette === "plain"/)
|
||||
assert.match(layoutSource, /: "plain"/)
|
||||
})
|
||||
|
||||
test("plain palette is available in the palette menu and messages", () => {
|
||||
assert.match(paletteSource, /value: "plain"[\s\S]*labelKey: "palette\.plain"/)
|
||||
assert.equal(zhMessages.palette.plain, "朴素默认")
|
||||
assert.equal(enMessages.palette.plain, "Plain Default")
|
||||
})
|
||||
@@ -1,7 +1,7 @@
|
||||
"use client"
|
||||
|
||||
import { useEffect, useState } from "react"
|
||||
import { DropletsIcon, PaletteIcon } from "lucide-react"
|
||||
import { CircleIcon, DropletsIcon, PaletteIcon } from "lucide-react"
|
||||
|
||||
import { useI18n } from "@/i18n/provider"
|
||||
import { Button } from "@/components/ui/button"
|
||||
@@ -13,16 +13,21 @@ import {
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu"
|
||||
|
||||
type PaletteMode = "blue" | "green" | "gray"
|
||||
type PaletteMode = "plain" | "blue" | "green" | "gray"
|
||||
|
||||
const PALETTE_STORAGE_KEY = "dashboard_palette"
|
||||
const DEFAULT_PALETTE: PaletteMode = "green"
|
||||
const DEFAULT_PALETTE: PaletteMode = "plain"
|
||||
|
||||
const paletteOptions: Array<{
|
||||
value: PaletteMode
|
||||
labelKey: string
|
||||
swatch: string
|
||||
}> = [
|
||||
{
|
||||
value: "plain",
|
||||
labelKey: "palette.plain",
|
||||
swatch: "bg-zinc-700",
|
||||
},
|
||||
{
|
||||
value: "green",
|
||||
labelKey: "palette.green",
|
||||
@@ -46,7 +51,10 @@ function readPalette(): PaletteMode {
|
||||
}
|
||||
|
||||
const stored = window.localStorage.getItem(PALETTE_STORAGE_KEY)
|
||||
return stored === "blue" || stored === "green" || stored === "gray"
|
||||
return stored === "plain" ||
|
||||
stored === "blue" ||
|
||||
stored === "green" ||
|
||||
stored === "gray"
|
||||
? stored
|
||||
: DEFAULT_PALETTE
|
||||
}
|
||||
@@ -68,12 +76,19 @@ export function PaletteToggle() {
|
||||
|
||||
function handleChange(value: string) {
|
||||
const nextPalette: PaletteMode =
|
||||
value === "blue" || value === "gray" ? value : "green"
|
||||
value === "blue" || value === "green" || value === "gray"
|
||||
? value
|
||||
: "plain"
|
||||
setPalette(nextPalette)
|
||||
applyPalette(nextPalette)
|
||||
}
|
||||
|
||||
const ActiveIcon = palette === "green" ? DropletsIcon : PaletteIcon
|
||||
const ActiveIcon =
|
||||
palette === "plain"
|
||||
? CircleIcon
|
||||
: palette === "green"
|
||||
? DropletsIcon
|
||||
: PaletteIcon
|
||||
|
||||
return (
|
||||
<DropdownMenu>
|
||||
|
||||
@@ -2364,6 +2364,7 @@
|
||||
},
|
||||
"palette": {
|
||||
"toggle": "Change accent color",
|
||||
"plain": "Default",
|
||||
"green": "Service Green",
|
||||
"gray": "Neutral Gray",
|
||||
"blue": "Clear Blue"
|
||||
|
||||
@@ -2364,6 +2364,7 @@
|
||||
},
|
||||
"palette": {
|
||||
"toggle": "切换主题色",
|
||||
"plain": "默认",
|
||||
"green": "温润服务绿",
|
||||
"gray": "中性精密灰",
|
||||
"blue": "清透科技蓝"
|
||||
|
||||
Reference in New Issue
Block a user