mirror of
https://github.com/shishantbiswas/bknd.git
synced 2026-03-16 04:27:21 +00:00
admin: added "system" theme option, check user pref
This commit is contained in:
@@ -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": {
|
||||||
|
|||||||
@@ -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"]
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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: "/",
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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__) {
|
||||||
|
|||||||
@@ -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 };
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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"));
|
||||||
|
|
||||||
|
|||||||
@@ -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]
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user