This is an automated email from the ASF dual-hosted git repository.
hsluoyz pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/casbin-gateway.git
The following commit(s) were added to refs/heads/master by this push:
new c859a77 feat(web): default to a clay palette
c859a77 is described below
commit c859a77250a13de7a10faa328d45e3be81c7f8f2
Author: Yang Luo <[email protected]>
AuthorDate: Mon Sep 28 17:01:38 2026 +0800
feat(web): default to a clay palette
---
web/src/Setting.tsx | 4 +-
web/src/components/shared/app-header.tsx | 20 ++++----
web/src/index.css | 83 ++++++++++++++++++++++++++++++++
web/src/locales/en/data.json | 1 +
web/src/locales/zh/data.json | 1 +
web/src/types.ts | 2 +-
6 files changed, 99 insertions(+), 12 deletions(-)
diff --git a/web/src/Setting.tsx b/web/src/Setting.tsx
index 8d2ac02..5464423 100644
--- a/web/src/Setting.tsx
+++ b/web/src/Setting.tsx
@@ -235,7 +235,7 @@ export function saveThemeAlgorithm(themeAlgorithm:
ThemeAlgorithm) {
// The palette is orthogonal to light/dark: each one defines both, so switching
// palettes never drags the reader out of the mode they chose.
-export const Palettes: Palette[] = ["amber", "terminal", "indigo", "neutral"];
+export const Palettes: Palette[] = ["clay", "amber", "terminal", "indigo",
"neutral"];
export function applyPalette(palette: Palette) {
document.documentElement.setAttribute("data-palette", palette);
@@ -243,7 +243,7 @@ export function applyPalette(palette: Palette) {
export function readPalette(): Palette {
const raw = localStorage.getItem("palette");
- return Palettes.includes(raw as Palette) ? (raw as Palette) : "amber";
+ return Palettes.includes(raw as Palette) ? (raw as Palette) : "clay";
}
export function savePalette(palette: Palette) {
diff --git a/web/src/components/shared/app-header.tsx
b/web/src/components/shared/app-header.tsx
index 1519fa4..7faf455 100644
--- a/web/src/components/shared/app-header.tsx
+++ b/web/src/components/shared/app-header.tsx
@@ -38,11 +38,12 @@ import {cn} from "@/lib/utils";
import {LogoMark} from "@/components/shared/logo";
import {VersionPanel} from "@/components/shared/version-panel";
-const bandButton = "text-band-foreground hover:bg-band-foreground/15
hover:text-band-foreground";
+const bandButton = "text-band-foreground hover:bg-band-foreground/10
hover:text-band-foreground";
// The swatches are literal rather than var(--primary): the menu has to show
the
// palette you are not in, and both colours have to read on either background.
const paletteSwatch: Record<Palette, string> = {
+ clay: "oklch(0.66 0.13 40)",
amber: "oklch(0.64 0.16 52)",
terminal: "oklch(0.66 0.13 200)",
indigo: "oklch(0.58 0.19 275)",
@@ -50,6 +51,7 @@ const paletteSwatch: Record<Palette, string> = {
};
const paletteLabel: Record<Palette, string> = {
+ clay: "general:Clay",
amber: "general:Amber & Ink",
terminal: "general:Terminal",
indigo: "general:Indigo",
@@ -182,9 +184,9 @@ function AccountMenu({
<DropdownMenuTrigger asChild>
<button
type="button"
- className="hover:bg-band-foreground/15 ml-1 flex items-center gap-2
rounded-full p-0.5 pr-2 transition-colors"
+ className="hover:bg-band-foreground/10 ml-1 flex items-center gap-2
rounded-full p-0.5 pr-2 transition-colors"
>
- <Avatar className="ring-band-foreground/40 ring-2">
+ <Avatar className="ring-band-foreground/25 ring-2">
{account.avatar ? <AvatarImage src={account.avatar} alt={name} />
: null}
<AvatarFallback style={{backgroundColor:
Setting.getAvatarColor(account.name), color: "#fff"}}>
{Setting.getShortName(account.name).slice(0, 2).toUpperCase()}
@@ -285,16 +287,16 @@ export function AppHeader({
return (
<>
- <header className="from-band to-band-end text-band-foreground
bg-gradient-to-br">
+ <header className="from-band to-band-end text-band-foreground border-b
bg-gradient-to-br">
<div className="flex flex-wrap items-center gap-x-4 gap-y-1 px-4 pt-2
md:h-22 md:flex-nowrap md:px-6 md:pt-0">
<Link to="/" className="flex shrink-0 items-center gap-2">
- <span className="bg-band-foreground/95 flex size-9 items-center
justify-center rounded-xl shadow-sm">
+ <span className="bg-card flex size-9 items-center justify-center
rounded-xl shadow-sm ring-1 ring-border">
<LogoMark className="size-7" />
</span>
- <span className="hidden text-base leading-tight font-semibold
lg:block">Casbin Gateway</span>
+ <span className="hidden text-base leading-tight font-semibold
xl:block">Casbin Gateway</span>
</Link>
- <nav className="order-3 -mx-1 flex w-full [scrollbar-width:none]
gap-1 overflow-x-auto pb-2 md:order-none md:mx-0 md:w-auto md:flex-1
md:justify-center md:pb-0">
+ <nav className="order-3 -mx-1 flex w-full [scrollbar-width:none]
gap-1 overflow-x-auto pb-2 md:order-none md:mx-0 md:w-auto md:flex-1
md:justify-center-safe md:pb-0">
{sections.map(section => {
const Icon = section.icon;
const selected = active?.key === section.key;
@@ -303,8 +305,8 @@ export function AppHeader({
key={section.key}
to={sectionPages(section, isAdmin)[0].path ??
section.pages[0]}
className={cn(
- "flex min-w-[68px] shrink-0 flex-col items-center gap-1
rounded-xl px-3 py-2 transition-colors md:min-w-[84px]",
- selected ? "bg-band-foreground/20 font-semibold
shadow-inner" : "hover:bg-band-foreground/10",
+ "flex min-w-[68px] shrink-0 flex-col items-center gap-1
rounded-xl px-3 py-2 transition-colors lg:min-w-[84px]",
+ selected ? "bg-band-foreground/12 font-semibold" :
"hover:bg-band-foreground/6",
)}
>
<Icon className="size-6 md:size-7" strokeWidth={1.75} />
diff --git a/web/src/index.css b/web/src/index.css
index 853b77c..9847519 100644
--- a/web/src/index.css
+++ b/web/src/index.css
@@ -101,6 +101,89 @@
--band-foreground: oklch(0.955 0.012 85);
}
+/* "Clay": Claude Desktop's colours. Warm ivory paper, near-black ink, and the
+ clay orange as the one accent; the band is a shade of the same paper rather
+ than a colour, so the page stays calm. */
+html[data-palette="clay"]:not(.dark) {
+ --radius: 0.625rem;
+
+ --background: oklch(0.982 0.005 95);
+ --foreground: oklch(0.220 0.004 70);
+ --card: oklch(0.997 0.002 95);
+ --card-foreground: oklch(0.220 0.004 70);
+ --popover: oklch(0.997 0.002 95);
+ --popover-foreground: oklch(0.220 0.004 70);
+ --primary: oklch(0.565 0.145 40);
+ --primary-foreground: oklch(0.990 0.004 95);
+ --secondary: oklch(0.955 0.008 95);
+ --secondary-foreground: oklch(0.280 0.006 70);
+ --muted: oklch(0.955 0.008 95);
+ --muted-foreground: oklch(0.540 0.009 90);
+ --accent: oklch(0.940 0.011 88);
+ --accent-foreground: oklch(0.260 0.006 70);
+ --destructive: oklch(0.540 0.180 27);
+ --destructive-foreground: oklch(0.990 0.004 95);
+ --success: oklch(0.525 0.110 150);
+ --success-foreground: oklch(0.990 0.004 95);
+ --warning: oklch(0.560 0.120 75);
+ --warning-foreground: oklch(0.990 0.004 95);
+ --info: oklch(0.530 0.110 250);
+ --info-foreground: oklch(0.990 0.004 95);
+ --border: oklch(0.905 0.010 90);
+ --input: oklch(0.885 0.012 90);
+ --ring: oklch(0.565 0.145 40);
+
+ --chart-1: oklch(0.660 0.130 40);
+ --chart-2: oklch(0.580 0.070 240);
+ --chart-3: oklch(0.700 0.110 85);
+ --chart-4: oklch(0.560 0.090 150);
+ --chart-5: oklch(0.560 0.110 300);
+
+ --band: oklch(0.958 0.008 95);
+ --band-end: oklch(0.940 0.011 88);
+ --band-foreground: oklch(0.220 0.004 70);
+}
+
+html[data-palette="clay"].dark {
+ --radius: 0.625rem;
+
+ --background: oklch(0.262 0.003 100);
+ --foreground: oklch(0.965 0.006 95);
+ --card: oklch(0.302 0.003 100);
+ --card-foreground: oklch(0.965 0.006 95);
+ --popover: oklch(0.302 0.003 100);
+ --popover-foreground: oklch(0.965 0.006 95);
+ --primary: oklch(0.700 0.135 40);
+ --primary-foreground: oklch(0.200 0.030 40);
+ --secondary: oklch(0.320 0.004 95);
+ --secondary-foreground: oklch(0.950 0.006 95);
+ --muted: oklch(0.320 0.004 95);
+ --muted-foreground: oklch(0.800 0.012 95);
+ --accent: oklch(0.340 0.005 90);
+ --accent-foreground: oklch(0.960 0.006 95);
+ --destructive: oklch(0.700 0.170 25);
+ --destructive-foreground: oklch(0.190 0.030 25);
+ --success: oklch(0.740 0.120 150);
+ --success-foreground: oklch(0.190 0.030 150);
+ --warning: oklch(0.790 0.120 80);
+ --warning-foreground: oklch(0.200 0.030 80);
+ --info: oklch(0.730 0.100 250);
+ --info-foreground: oklch(0.190 0.030 250);
+ --border: oklch(0.95 0.010 95 / 12%);
+ --input: oklch(0.95 0.010 95 / 18%);
+ --ring: oklch(0.700 0.135 40);
+
+ --chart-1: oklch(0.700 0.135 40);
+ --chart-2: oklch(0.700 0.070 240);
+ --chart-3: oklch(0.790 0.110 85);
+ --chart-4: oklch(0.700 0.100 150);
+ --chart-5: oklch(0.700 0.110 300);
+
+ --band: oklch(0.228 0.003 90);
+ --band-end: oklch(0.215 0.003 90);
+ --band-foreground: oklch(0.965 0.006 95);
+}
+
/* "Terminal": a console, so the greys go cool, the corners go square and the
accent is the cyan a terminal picks for something you can act on. Phosphor
green would have been the obvious accent and is the reason this is not:
green
diff --git a/web/src/locales/en/data.json b/web/src/locales/en/data.json
index 1c30230..dc5063f 100644
--- a/web/src/locales/en/data.json
+++ b/web/src/locales/en/data.json
@@ -1041,6 +1041,7 @@
"Checkup routed ok": "{count} agents routed through Gateway",
"Checkup updates failed": "{count} agents have a newer release",
"Checkup updates ok": "Every agent is up to date",
+ "Clay": "Clay",
"Client ip": "Client ip",
"Close": "Close",
"Copied": "Copied",
diff --git a/web/src/locales/zh/data.json b/web/src/locales/zh/data.json
index 9f0aacc..f0b261e 100644
--- a/web/src/locales/zh/data.json
+++ b/web/src/locales/zh/data.json
@@ -1227,6 +1227,7 @@
"Checkup routed ok": "{count}个Agent已接入Gateway",
"Checkup updates failed": "{count}个Agent有新版本",
"Checkup updates ok": "Agent均为最新版本",
+ "Clay": "陶土",
"Client ip": "客户端IP",
"Close": "关闭",
"Copied": "已复制",
diff --git a/web/src/types.ts b/web/src/types.ts
index 3c0d0e3..d3044be 100644
--- a/web/src/types.ts
+++ b/web/src/types.ts
@@ -16,7 +16,7 @@
export type ThemeAlgorithm = ("default" | "dark")[];
/** Which colour set the theme draws from, light or dark; see index.css. */
-export type Palette = "amber" | "terminal" | "indigo" | "neutral";
+export type Palette = "clay" | "amber" | "terminal" | "indigo" | "neutral";
/**
* The envelope every /api handler returns (controllers.Response): "ok" or
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]