fix bknd theme

This commit is contained in:
dswbx
2025-02-06 15:00:54 +01:00
parent e14d528386
commit 0a5cc2ad98
14 changed files with 82 additions and 52 deletions

View File

@@ -70,7 +70,8 @@ export class AdminController extends Controller {
hono.use("*", async (c, next) => { hono.use("*", async (c, next) => {
const obj = { const obj = {
user: auth.authenticator?.getUser(), user: auth.authenticator?.getUser(),
logout_route: this.withBasePath(authRoutes.logout) logout_route: this.withBasePath(authRoutes.logout),
color_scheme: configs.server.admin.color_scheme
}; };
const html = await this.getHtml(obj); const html = await this.getHtml(obj);
if (!html) { if (!html) {

View File

@@ -3,6 +3,7 @@ import { Notifications } from "@mantine/notifications";
import type { ModuleConfigs } from "modules"; import type { ModuleConfigs } from "modules";
import React from "react"; import React from "react";
import { BkndProvider, useBknd } from "ui/client/bknd"; import { BkndProvider, useBknd } from "ui/client/bknd";
import { useTheme } from "ui/client/use-theme";
import { Logo } from "ui/components/display/Logo"; import { Logo } from "ui/components/display/Logo";
import * as AppShell from "ui/layouts/AppShell/AppShell"; import * as AppShell from "ui/layouts/AppShell/AppShell";
import { FlashMessage } from "ui/modules/server/FlashMessage"; import { FlashMessage } from "ui/modules/server/FlashMessage";
@@ -40,8 +41,7 @@ export default function Admin({
} }
function AdminInternal() { function AdminInternal() {
const b = useBknd(); const { theme } = useTheme();
const theme = b.app.getAdminConfig().color_scheme;
return ( return (
<MantineProvider {...createMantineTheme(theme ?? "light")}> <MantineProvider {...createMantineTheme(theme ?? "light")}>

View File

@@ -15,6 +15,7 @@ type BkndContext = {
actions: ReturnType<typeof getSchemaActions>; actions: ReturnType<typeof getSchemaActions>;
app: AppReduced; app: AppReduced;
adminOverride?: ModuleConfigs["server"]["admin"]; adminOverride?: ModuleConfigs["server"]["admin"];
fallback: boolean;
}; };
const BkndContext = createContext<BkndContext>(undefined!); const BkndContext = createContext<BkndContext>(undefined!);
@@ -37,7 +38,7 @@ export function BkndProvider({
>) { >) {
const [withSecrets, setWithSecrets] = useState<boolean>(includeSecrets); const [withSecrets, setWithSecrets] = useState<boolean>(includeSecrets);
const [schema, setSchema] = const [schema, setSchema] =
useState<Pick<BkndContext, "version" | "schema" | "config" | "permissions">>(); useState<Pick<BkndContext, "version" | "schema" | "config" | "permissions" | "fallback">>();
const [fetched, setFetched] = useState(false); const [fetched, setFetched] = useState(false);
const [error, setError] = useState<boolean>(); const [error, setError] = useState<boolean>();
const errorShown = useRef<boolean>(); const errorShown = useRef<boolean>();
@@ -78,7 +79,8 @@ export function BkndProvider({
version: 0, version: 0,
schema: getDefaultSchema(), schema: getDefaultSchema(),
config: getDefaultConfig(), config: getDefaultConfig(),
permissions: [] permissions: [],
fallback: true
} as any); } as any);
if (adminOverride) { if (adminOverride) {

View File

@@ -60,6 +60,7 @@ export const useBaseUrl = () => {
type BkndWindowContext = { type BkndWindowContext = {
user?: TApiUser; user?: TApiUser;
logout_route: string; logout_route: string;
color_scheme?: "light" | "dark";
}; };
export function useBkndWindowContext(): BkndWindowContext { export function useBkndWindowContext(): BkndWindowContext {
if (typeof window !== "undefined" && window.__BKND__) { if (typeof window !== "undefined" && window.__BKND__) {

View File

@@ -1,8 +1,9 @@
import { useBknd } from "ui/client/bknd"; import { useBknd } from "ui/client/bknd";
import { useTheme } from "ui/client/use-theme";
export function useBkndSystem() { export function useBkndSystem() {
const { config, schema, actions: bkndActions } = useBknd(); const { config, schema, actions: bkndActions } = useBknd();
const theme = config.server.admin.color_scheme ?? "light"; const { theme } = useTheme();
const actions = { const actions = {
theme: { theme: {

View File

@@ -1,8 +1,18 @@
import { useBkndWindowContext } from "ui/client/ClientProvider";
import { useBknd } from "ui/client/bknd"; import { useBknd } from "ui/client/bknd";
export function useTheme(): { theme: "light" | "dark" } { export type Theme = "light" | "dark";
const b = useBknd();
const theme = b.app.getAdminConfig().color_scheme as any;
return { theme }; export function useTheme(fallback: Theme = "light"): { theme: Theme } {
const b = useBknd();
const winCtx = useBkndWindowContext();
if (b) {
if (b?.adminOverride?.color_scheme) {
return { theme: b.adminOverride.color_scheme };
} else if (!b.fallback) {
return { theme: b.config.server.admin.color_scheme ?? fallback };
}
}
return { theme: winCtx.color_scheme ?? fallback };
} }

View File

@@ -1,13 +1,13 @@
import { useBknd } from "ui/client/bknd"; import { useTheme } from "ui/client/use-theme";
export function Logo({ export function Logo({
scale = 0.2, scale = 0.2,
fill, fill,
theme = "light" ...props
}: { scale?: number; fill?: string; theme?: string }) { }: { scale?: number; fill?: string; theme?: string }) {
const $bknd = useBknd(); const t = useTheme();
const _theme = theme ?? $bknd?.app?.getAdminConfig().color_scheme ?? "light"; const theme = props.theme ?? t.theme;
const svgFill = fill ? fill : _theme === "light" ? "black" : "white"; const svgFill = fill ? fill : theme === "light" ? "black" : "white";
const dim = { const dim = {
width: Math.round(578 * scale), width: Math.round(578 * scale),

View File

@@ -68,7 +68,11 @@ export function FieldWrapper({
)} )}
{label && ( {label && (
<Formy.Label as={wrapper === "fieldset" ? "legend" : "label"} htmlFor={pointer}> <Formy.Label
as={wrapper === "fieldset" ? "legend" : "label"}
htmlFor={pointer}
className="self-start"
>
{label} {required && <span className="font-medium opacity-30">*</span>} {label} {required && <span className="font-medium opacity-30">*</span>}
</Formy.Label> </Formy.Label>
)} )}

View File

@@ -22,9 +22,17 @@ export function SocialLink({
basepath = "/api/auth", basepath = "/api/auth",
children children
}: SocialLinkProps) { }: SocialLinkProps) {
const url = [basepath, provider, action].join("/");
return ( return (
<form method={method} action={[basepath, name, action].join("/")} className="w-full"> <form method={method} action={url} className="w-full">
<Button type="submit" size="large" variant="outline" className="justify-center w-full"> <Button
type="submit"
size="large"
variant="outline"
className="justify-center w-full"
IconLeft={icon}
>
Continue with {label ?? ucFirstAllSnakeToPascalWithSpaces(provider)} Continue with {label ?? ucFirstAllSnakeToPascalWithSpaces(provider)}
</Button> </Button>
{children} {children}

View File

@@ -364,7 +364,7 @@ export const SectionHeaderAccordionItem = ({
); );
export const Separator = ({ className, ...props }: ComponentPropsWithoutRef<"hr">) => ( export const Separator = ({ className, ...props }: ComponentPropsWithoutRef<"hr">) => (
<hr {...props} className={twMerge("bg-primary/50 my-3", className)} /> <hr {...props} className={twMerge("border-muted my-3", className)} />
); );
export { Header } from "./Header"; export { Header } from "./Header";

View File

@@ -13,6 +13,7 @@ import {
import { useAuth, useBkndWindowContext } from "ui/client"; import { useAuth, useBkndWindowContext } from "ui/client";
import { useBknd } from "ui/client/bknd"; import { useBknd } from "ui/client/bknd";
import { useBkndSystemTheme } from "ui/client/schema/system/use-bknd-system"; import { useBkndSystemTheme } from "ui/client/schema/system/use-bknd-system";
import { useTheme } from "ui/client/use-theme";
import { Button } from "ui/components/buttons/Button"; import { Button } from "ui/components/buttons/Button";
import { IconButton } from "ui/components/buttons/IconButton"; import { IconButton } from "ui/components/buttons/IconButton";
import { Logo } from "ui/components/display/Logo"; import { Logo } from "ui/components/display/Logo";
@@ -114,9 +115,9 @@ function SidebarToggler() {
} }
export function Header({ hasSidebar = true }) { export function Header({ hasSidebar = true }) {
//const logoReturnPath = "";
const { app } = useBknd(); const { app } = useBknd();
const { logo_return_path = "/", color_scheme = "light" } = app.getAdminConfig(); const { theme } = useTheme();
const { logo_return_path = "/" } = app.getAdminConfig();
return ( return (
<header <header
@@ -128,7 +129,7 @@ export function Header({ hasSidebar = true }) {
native={logo_return_path !== "/"} native={logo_return_path !== "/"}
className="max-h-full flex hover:bg-primary/5 link p-2.5 w-[134px] outline-none" className="max-h-full flex hover:bg-primary/5 link p-2.5 w-[134px] outline-none"
> >
<Logo theme={color_scheme} /> <Logo theme={theme} />
</Link> </Link>
<HeaderNavigation /> <HeaderNavigation />
<div className="flex flex-grow" /> <div className="flex flex-grow" />

View File

@@ -2,6 +2,35 @@
@tailwind components; @tailwind components;
@tailwind utilities; @tailwind utilities;
#bknd-admin.dark,
.dark .bknd-admin {
--color-primary: 250 250 250; /* zinc-50 */
--color-background: 30 31 34;
--color-muted: 47 47 52;
--color-darkest: 255 255 255; /* white */
--color-lightest: 24 24 27; /* black */
}
#bknd-admin,
.bknd-admin {
--color-primary: 9 9 11; /* zinc-950 */
--color-background: 250 250 250; /* zinc-50 */
--color-muted: 228 228 231; /* ? */
--color-darkest: 0 0 0; /* black */
--color-lightest: 255 255 255; /* white */
@mixin light {
--mantine-color-body: rgb(250 250 250);
}
@mixin dark {
--mantine-color-body: rgb(9 9 11);
}
table {
font-size: inherit;
}
}
#bknd-admin { #bknd-admin {
@apply bg-background text-primary overflow-hidden h-dvh w-dvw; @apply bg-background text-primary overflow-hidden h-dvh w-dvw;

View File

@@ -1,5 +1,6 @@
import { Suspense, lazy } from "react"; import { Suspense, lazy } from "react";
import { useBknd } from "ui/client/bknd"; import { useBknd } from "ui/client/bknd";
import { useTheme } from "ui/client/use-theme";
import { Route, Router, Switch } from "wouter"; import { Route, Router, Switch } from "wouter";
import AuthRoutes from "./auth"; import AuthRoutes from "./auth";
import { AuthLogin } from "./auth/auth.login"; import { AuthLogin } from "./auth/auth.login";
@@ -20,11 +21,11 @@ const TestRoutes = lazy(() => import("./test"));
export function Routes() { export function Routes() {
const { app } = useBknd(); const { app } = useBknd();
const { color_scheme: theme } = app.getAdminConfig(); const { theme } = useTheme();
const { basepath } = app.getAdminConfig(); const { basepath } = app.getAdminConfig();
return ( return (
<div id="bknd-admin" className={(theme ?? "light") + " antialiased"}> <div id="bknd-admin" className={theme + " antialiased"}>
<Router base={basepath}> <Router base={basepath}>
<Switch> <Switch>
<Route path="/auth/login" component={AuthLogin} /> <Route path="/auth/login" component={AuthLogin} />

View File

@@ -16,34 +16,6 @@ html.fixed body {
touch-action: none; touch-action: none;
} }
#bknd-admin,
.bknd-admin {
--color-primary: 9 9 11; /* zinc-950 */
--color-background: 250 250 250; /* zinc-50 */
--color-muted: 228 228 231; /* ? */
--color-darkest: 0 0 0; /* black */
--color-lightest: 255 255 255; /* white */
&.dark {
--color-primary: 250 250 250; /* zinc-50 */
--color-background: 30 31 34;
--color-muted: 47 47 52;
--color-darkest: 255 255 255; /* white */
--color-lightest: 24 24 27; /* black */
}
@mixin light {
--mantine-color-body: rgb(250 250 250);
}
@mixin dark {
--mantine-color-body: rgb(9 9 11);
}
table {
font-size: inherit;
}
}
html, html,
body { body {
font-size: 14px; font-size: 14px;