diff --git a/app/package.json b/app/package.json index 970af13..c349f60 100644 --- a/app/package.json +++ b/app/package.json @@ -3,7 +3,7 @@ "type": "module", "sideEffects": false, "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.", "homepage": "https://bknd.io", "repository": { diff --git a/app/src/modules/server/AdminController.tsx b/app/src/modules/server/AdminController.tsx index 32c0c4e..c31bad0 100644 --- a/app/src/modules/server/AdminController.tsx +++ b/app/src/modules/server/AdminController.tsx @@ -7,6 +7,7 @@ import { html } from "hono/html"; import { Fragment } from "hono/jsx"; import { Controller } from "modules/Controller"; import * as SystemPermissions from "modules/permissions"; +import type { AppTheme } from "modules/server/AppServer"; const htmlBkndContextReplace = ""; @@ -246,7 +247,7 @@ export class AdminController extends Controller { } } -const style = (theme: "light" | "dark" = "light") => { +const style = (theme: AppTheme) => { const base = { margin: 0, padding: 0, @@ -271,6 +272,6 @@ const style = (theme: "light" | "dark" = "light") => { return { ...base, - ...styles[theme] + ...styles[theme === "light" ? "light" : "dark"] }; }; diff --git a/app/src/modules/server/AppServer.ts b/app/src/modules/server/AppServer.ts index c189262..9b4e6bf 100644 --- a/app/src/modules/server/AppServer.ts +++ b/app/src/modules/server/AppServer.ts @@ -4,12 +4,15 @@ import { cors } from "hono/cors"; import { Module } from "modules/Module"; 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( { admin: Type.Object( { 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( Type.String({ default: "/", diff --git a/app/src/ui/Admin.tsx b/app/src/ui/Admin.tsx index d966266..38d6cec 100644 --- a/app/src/ui/Admin.tsx +++ b/app/src/ui/Admin.tsx @@ -44,7 +44,7 @@ function AdminInternal() { const { theme } = useTheme(); return ( - + diff --git a/app/src/ui/client/ClientProvider.tsx b/app/src/ui/client/ClientProvider.tsx index fc7fb3a..7328633 100644 --- a/app/src/ui/client/ClientProvider.tsx +++ b/app/src/ui/client/ClientProvider.tsx @@ -1,4 +1,5 @@ import { Api, type ApiOptions, type TApiUser } from "Api"; +import type { AppTheme } from "modules/server/AppServer"; import { createContext, useContext } from "react"; const ClientContext = createContext<{ baseUrl: string; api: Api }>({ @@ -60,7 +61,7 @@ export const useBaseUrl = () => { type BkndWindowContext = { user?: TApiUser; logout_route: string; - color_scheme?: "light" | "dark"; + color_scheme?: AppTheme; }; export function useBkndWindowContext(): BkndWindowContext { if (typeof window !== "undefined" && window.__BKND__) { diff --git a/app/src/ui/client/use-theme.ts b/app/src/ui/client/use-theme.ts index 5fce405..935c1c1 100644 --- a/app/src/ui/client/use-theme.ts +++ b/app/src/ui/client/use-theme.ts @@ -1,18 +1,26 @@ +import type { AppTheme } from "modules/server/AppServer"; import { useBkndWindowContext } from "ui/client/ClientProvider"; import { useBknd } from "ui/client/bknd"; -export type Theme = "light" | "dark"; - -export function useTheme(fallback: Theme = "light"): { theme: Theme } { +export function useTheme(fallback: AppTheme = "system"): { theme: AppTheme } { 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 }; - } + + // 1. override + // 2. config + // 3. winCtx + // 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 }; } diff --git a/app/src/ui/routes/index.tsx b/app/src/ui/routes/index.tsx index c1e5919..db1fb0f 100644 --- a/app/src/ui/routes/index.tsx +++ b/app/src/ui/routes/index.tsx @@ -10,12 +10,6 @@ import MediaRoutes from "./media"; import { Root, RootEmpty } from "./root"; 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 const TestRoutes = lazy(() => import("./test")); diff --git a/app/tailwind.config.js b/app/tailwind.config.js index fa735bd..cf7879c 100644 --- a/app/tailwind.config.js +++ b/app/tailwind.config.js @@ -1,3 +1,5 @@ +import tailwindCssAnimate from "tailwindcss-animate"; + /** @type {import("tailwindcss").Config} */ export default { content: ["./index.html", "./src/ui/**/*.tsx", "./src/ui/lib/mantine/theme.ts"], @@ -13,5 +15,5 @@ export default { } } }, - plugins: [require("tailwindcss-animate")] + plugins: [tailwindCssAnimate] }; diff --git a/bun.lockb b/bun.lockb index 63c76bc..2fa9b69 100755 Binary files a/bun.lockb and b/bun.lockb differ