admin: added "system" theme option, check user pref

This commit is contained in:
dswbx
2025-02-18 08:20:41 +01:00
parent bd362607ae
commit 0823b182f6
9 changed files with 32 additions and 23 deletions

View File

@@ -3,7 +3,7 @@
"type": "module", "type": "module",
"sideEffects": false, "sideEffects": false,
"bin": "./dist/cli/index.js", "bin": "./dist/cli/index.js",
"version": "0.8.0-rc.5", "version": "0.8.0-rc.6",
"description": "Lightweight Firebase/Supabase alternative built to run anywhere — incl. Next.js, Remix, Astro, Cloudflare, Bun, Node, AWS Lambda & more.", "description": "Lightweight Firebase/Supabase alternative built to run anywhere — incl. Next.js, Remix, Astro, Cloudflare, Bun, Node, AWS Lambda & more.",
"homepage": "https://bknd.io", "homepage": "https://bknd.io",
"repository": { "repository": {

View File

@@ -7,6 +7,7 @@ import { html } from "hono/html";
import { Fragment } from "hono/jsx"; import { Fragment } from "hono/jsx";
import { Controller } from "modules/Controller"; import { Controller } from "modules/Controller";
import * as SystemPermissions from "modules/permissions"; import * as SystemPermissions from "modules/permissions";
import type { AppTheme } from "modules/server/AppServer";
const htmlBkndContextReplace = "<!-- BKND_CONTEXT -->"; const htmlBkndContextReplace = "<!-- BKND_CONTEXT -->";
@@ -246,7 +247,7 @@ export class AdminController extends Controller {
} }
} }
const style = (theme: "light" | "dark" = "light") => { const style = (theme: AppTheme) => {
const base = { const base = {
margin: 0, margin: 0,
padding: 0, padding: 0,
@@ -271,6 +272,6 @@ const style = (theme: "light" | "dark" = "light") => {
return { return {
...base, ...base,
...styles[theme] ...styles[theme === "light" ? "light" : "dark"]
}; };
}; };

View File

@@ -4,12 +4,15 @@ import { cors } from "hono/cors";
import { Module } from "modules/Module"; import { Module } from "modules/Module";
const serverMethods = ["GET", "POST", "PATCH", "PUT", "DELETE"]; const serverMethods = ["GET", "POST", "PATCH", "PUT", "DELETE"];
const appThemes = ["dark", "light", "system"] as const;
export type AppTheme = (typeof appThemes)[number];
export const serverConfigSchema = Type.Object( export const serverConfigSchema = Type.Object(
{ {
admin: Type.Object( admin: Type.Object(
{ {
basepath: Type.Optional(Type.String({ default: "", pattern: "^(/.+)?$" })), basepath: Type.Optional(Type.String({ default: "", pattern: "^(/.+)?$" })),
color_scheme: Type.Optional(StringEnum(["dark", "light"], { default: "light" })), color_scheme: Type.Optional(StringEnum(["dark", "light", "system"])),
logo_return_path: Type.Optional( logo_return_path: Type.Optional(
Type.String({ Type.String({
default: "/", default: "/",

View File

@@ -44,7 +44,7 @@ function AdminInternal() {
const { theme } = useTheme(); const { theme } = useTheme();
return ( return (
<MantineProvider {...createMantineTheme(theme ?? "light")}> <MantineProvider {...createMantineTheme(theme as any)}>
<Notifications /> <Notifications />
<FlashMessage /> <FlashMessage />
<BkndModalsProvider> <BkndModalsProvider>

View File

@@ -1,4 +1,5 @@
import { Api, type ApiOptions, type TApiUser } from "Api"; import { Api, type ApiOptions, type TApiUser } from "Api";
import type { AppTheme } from "modules/server/AppServer";
import { createContext, useContext } from "react"; import { createContext, useContext } from "react";
const ClientContext = createContext<{ baseUrl: string; api: Api }>({ const ClientContext = createContext<{ baseUrl: string; api: Api }>({
@@ -60,7 +61,7 @@ export const useBaseUrl = () => {
type BkndWindowContext = { type BkndWindowContext = {
user?: TApiUser; user?: TApiUser;
logout_route: string; logout_route: string;
color_scheme?: "light" | "dark"; color_scheme?: AppTheme;
}; };
export function useBkndWindowContext(): BkndWindowContext { export function useBkndWindowContext(): BkndWindowContext {
if (typeof window !== "undefined" && window.__BKND__) { if (typeof window !== "undefined" && window.__BKND__) {

View File

@@ -1,18 +1,26 @@
import type { AppTheme } from "modules/server/AppServer";
import { useBkndWindowContext } from "ui/client/ClientProvider"; import { useBkndWindowContext } from "ui/client/ClientProvider";
import { useBknd } from "ui/client/bknd"; import { useBknd } from "ui/client/bknd";
export type Theme = "light" | "dark"; export function useTheme(fallback: AppTheme = "system"): { theme: AppTheme } {
export function useTheme(fallback: Theme = "light"): { theme: Theme } {
const b = useBknd(); const b = useBknd();
const winCtx = useBkndWindowContext(); const winCtx = useBkndWindowContext();
if (b) {
if (b?.adminOverride?.color_scheme) { // 1. override
return { theme: b.adminOverride.color_scheme }; // 2. config
} else if (!b.fallback) { // 3. winCtx
return { theme: b.config.server.admin.color_scheme ?? fallback }; // 4. fallback
} // 5. default
const override = b?.adminOverride?.color_scheme;
const config = b?.config.server.admin.color_scheme;
const win = winCtx.color_scheme;
const prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
const theme = override ?? config ?? win ?? fallback;
if (theme === "system") {
return { theme: prefersDark ? "dark" : "light" };
} }
return { theme: winCtx.color_scheme ?? fallback }; return { theme };
} }

View File

@@ -10,12 +10,6 @@ import MediaRoutes from "./media";
import { Root, RootEmpty } from "./root"; import { Root, RootEmpty } from "./root";
import SettingsRoutes from "./settings"; import SettingsRoutes from "./settings";
/*const DataRoutes = lazy(() => import("./data"));
const AuthRoutes = lazy(() => import("./auth"));
const MediaRoutes = lazy(() => import("./media"));
const FlowRoutes = lazy(() => import("./flows"));
const SettingsRoutes = lazy(() => import("./settings"));*/
// @ts-ignore // @ts-ignore
const TestRoutes = lazy(() => import("./test")); const TestRoutes = lazy(() => import("./test"));

View File

@@ -1,3 +1,5 @@
import tailwindCssAnimate from "tailwindcss-animate";
/** @type {import("tailwindcss").Config} */ /** @type {import("tailwindcss").Config} */
export default { export default {
content: ["./index.html", "./src/ui/**/*.tsx", "./src/ui/lib/mantine/theme.ts"], content: ["./index.html", "./src/ui/**/*.tsx", "./src/ui/lib/mantine/theme.ts"],
@@ -13,5 +15,5 @@ export default {
} }
} }
}, },
plugins: [require("tailwindcss-animate")] plugins: [tailwindCssAnimate]
}; };

BIN
bun.lockb

Binary file not shown.