Make entire HK admin panel cohesive and always readable
Local Build and Deploy / deploy (push) Successful in 1m4s
Local Build and Deploy / deploy (push) Successful in 1m4s
- Remap shared shadcn semantic tokens (--color-primary, --color-popover, --color-card, --color-border, --color-ring, --color-muted-foreground, --color-destructive, ...) onto the admin palette for any page scoped with body:has([data-admin]); this themes every embedded Button, Badge, Input, Select, Card, Table, Tabs, Dialog, Switch, Checkbox with the admin theme and guaranteed contrast, without editing component files. Gated so the public site is untouched and Radix portals (dialogs/selects) are covered. - Tag the admin layout/sidebar with data-admin and give the admin content area the admin canvas background so the whole HK is one cohesive dark UI. - Fix hardcoded colors in catalog shop preview and favicon form to use admin variables; fix white text on a light warning tint (low contrast).
This commit is contained in:
1 parent
8721cfcea4
commit
0b18a16a2d
4 files changed
+48
-10
No files matched your search
@@ -76,7 +76,7 @@ export function FaviconForm({ currentUrl }: { currentUrl: string | null }) {
|
||||
alt="Favicon preview"
|
||||
width={64}
|
||||
height={64}
|
||||
className="rounded-lg border-2 border-[var(--admin-border)] object-contain bg-white"
|
||||
className="rounded-lg border-2 border-[var(--admin-border)] object-contain bg-[var(--admin-surface)]"
|
||||
unoptimized
|
||||
/>
|
||||
<div className="text-xs text-[var(--admin-text-muted)] break-all">{preview}</div>
|
||||
|
||||
@@ -165,7 +165,11 @@ export default async function AdminLayout({ children }: { children: ReactNode })
|
||||
|
||||
return (
|
||||
<AdminMobileWrapper sidebar={<Sidebar staff={staff} />}>
|
||||
<div className="flex flex-col min-w-0 p-5 lg:p-6">
|
||||
<div
|
||||
data-admin
|
||||
className="flex flex-col min-w-0 p-5 lg:p-6 min-h-screen"
|
||||
style={{ backgroundColor: "var(--admin-canvas)" }}
|
||||
>
|
||||
<Topbar staff={staff} />
|
||||
<section className="admin-page flex-1">{children}</section>
|
||||
</div>
|
||||
@@ -179,7 +183,7 @@ async function Sidebar({ staff }: { staff: { id: number; username: string; rank:
|
||||
const navGroups = getNavGroups(t);
|
||||
|
||||
return (
|
||||
<aside className="sticky top-0 self-start h-auto lg:h-screen overflow-y-auto bg-[var(--admin-sidebar-background)] text-[var(--admin-sidebar-text-readable)] shadow-xl flex flex-col">
|
||||
<aside data-admin className="sticky top-0 self-start h-auto lg:h-screen overflow-y-auto bg-[var(--admin-sidebar-background)] text-[var(--admin-sidebar-text-readable)] shadow-xl flex flex-col">
|
||||
<div className="flex items-center gap-3 px-4 py-5 border-b border-[var(--admin-border)]">
|
||||
<span
|
||||
className="flex-none w-10 h-10 rounded-xl grid place-items-center font-extrabold text-base text-[var(--color-primary-foreground-readable)] bg-[var(--admin-accent)] shadow-lg shadow-[var(--admin-accent)]/20"
|
||||
|
||||
@@ -1055,3 +1055,37 @@ tbody tr:hover {
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
}
|
||||
|
||||
/* ── Admin (HK) semantic token remap ──────────────────────────────────────
|
||||
Shared shadcn UI primitives (Button, Badge, Input, Select, Card, Table,
|
||||
Tabs, Dialog, Switch, Checkbox, Tooltip, …) are built on the site's
|
||||
semantic tokens (--color-background, --color-primary, --color-popover,
|
||||
--color-border, --color-ring, --color-muted-foreground, …). On admin
|
||||
pages we remap those tokens onto the admin palette so every embedded
|
||||
component renders with the admin theme and guaranteed contrast, without
|
||||
touching any component file.
|
||||
|
||||
Gated by `body:has([data-admin])` so the public site is completely
|
||||
unaffected. This also covers Radix portals (Dialog/Select/Dropdown/
|
||||
Popover/Tooltip) which mount under <body>. */
|
||||
body:has([data-admin]) {
|
||||
--color-foreground: var(--admin-text);
|
||||
--color-card: var(--admin-surface);
|
||||
--color-card-foreground: var(--admin-text);
|
||||
--color-popover: var(--admin-surface);
|
||||
--color-popover-foreground: var(--admin-text);
|
||||
--color-primary: var(--admin-accent);
|
||||
--color-primary-hover: color-mix(in srgb, var(--admin-accent) 84%, #000000);
|
||||
--color-primary-foreground: var(--admin-accent-foreground);
|
||||
--color-secondary: color-mix(in srgb, var(--admin-accent) 14%, var(--admin-surface));
|
||||
--color-secondary-foreground: var(--admin-text);
|
||||
--color-muted: color-mix(in srgb, var(--admin-text) 9%, var(--admin-surface));
|
||||
--color-muted-foreground: var(--admin-text-muted);
|
||||
--color-accent: color-mix(in srgb, var(--admin-accent) 16%, var(--admin-surface));
|
||||
--color-accent-foreground: var(--admin-text);
|
||||
--color-destructive: var(--admin-error);
|
||||
--color-destructive-foreground: var(--admin-error-foreground);
|
||||
--color-border: var(--admin-border);
|
||||
--color-input: var(--admin-border);
|
||||
--color-ring: var(--admin-accent);
|
||||
}
|
||||
@@ -35,8 +35,8 @@ export function ItemsShopPreview({
|
||||
const tileSize = getTileSize(layout);
|
||||
|
||||
return (
|
||||
<div className="rounded-lg border bg-gradient-to-b from-sky-50 to-sky-100 dark:from-slate-900 dark:to-slate-950 p-4">
|
||||
<div className="mb-3 flex items-center justify-between text-xs text-muted-foreground">
|
||||
<div className="rounded-lg border bg-gradient-to-b from-[var(--admin-surface)] to-[var(--admin-canvas)] p-4">
|
||||
<div className="mb-3 flex items-center justify-between text-xs text-[var(--admin-text-muted)]">
|
||||
<span className="font-medium">Shop preview · {layout}</span>
|
||||
<span>{items.length} items</span>
|
||||
</div>
|
||||
@@ -75,13 +75,13 @@ export function ItemsShopPreview({
|
||||
{/* Badges overlay */}
|
||||
<div className="absolute right-1 top-1 flex flex-col gap-0.5">
|
||||
{isClub && (
|
||||
<Badge className="h-4 gap-0.5 border-0 bg-[var(--admin-warning-subtle)] px-1 text-[8px] text-white">
|
||||
<Badge className="h-4 gap-0.5 border-0 bg-[var(--admin-warning-subtle)] px-1 text-[8px] text-[var(--admin-warning)]">
|
||||
<Crown className="h-2.5 w-2.5" />
|
||||
HC
|
||||
</Badge>
|
||||
)}
|
||||
{isOffer && (
|
||||
<Badge className="h-4 gap-0.5 border-0 bg-rose-500/90 px-1 text-[8px] text-white">
|
||||
<Badge className="h-4 gap-0.5 border-0 bg-[var(--admin-error)] px-1 text-[8px] text-[var(--admin-error-foreground)]">
|
||||
<Sparkles className="h-2.5 w-2.5" />
|
||||
OFFER
|
||||
</Badge>
|
||||
@@ -90,15 +90,15 @@ export function ItemsShopPreview({
|
||||
|
||||
{/* Amount badge */}
|
||||
{item.amount > 1 && (
|
||||
<Badge className="absolute left-1 top-1 h-4 border-0 bg-black/70 px-1 text-[9px] text-white">
|
||||
<Badge className="absolute left-1 top-1 h-4 border-0 bg-[var(--admin-surface)] px-1 text-[9px] text-[var(--admin-text)]">
|
||||
x{item.amount}
|
||||
</Badge>
|
||||
)}
|
||||
|
||||
{/* Limited */}
|
||||
{item.limitedStack > 0 && (
|
||||
<Badge className="absolute bottom-1 left-1 h-4 border-0 bg-purple-600/90 px-1 text-[8px] text-white">
|
||||
LTD {item.limitedSells}/{item.limitedStack}
|
||||
<Badge className="absolute bottom-1 left-1 h-4 border-0 bg-[var(--admin-accent)] px-1 text-[8px] text-[var(--admin-accent-foreground)]">
|
||||
LTD {item.limitedSells}/{item.limitedStack}
|
||||
</Badge>
|
||||
)}
|
||||
</div>
|
||||
|
||||
Reference in new issue
Block a user