feat: remove dark mode toggle, switch to prefers-color-scheme

This means it's not possible to manually change the theme, but all major operating systems
support global dark mode now, so it shouldn't be a huge problem.
Will re-add the dark mode toggle if the Sec-CH-Prefers-Color-Scheme header gets added to Firefox and Safari.
This commit is contained in:
sam 2024-09-25 15:14:48 +02:00
parent 862a64840e
commit 0f3ab19f6f
Signed by: sam
GPG key ID: B4EF20DDE721CAA1
9 changed files with 25 additions and 64 deletions

View file

@ -1,20 +1,7 @@
$font-family-sans-serif:
"FiraGO",
system-ui,
-apple-system,
"Segoe UI",
Roboto,
"Helvetica Neue",
"Noto Sans",
"Liberation Sans",
Arial,
sans-serif,
"Apple Color Emoji",
"Segoe UI Emoji",
"Segoe UI Symbol",
"Noto Color Emoji" !default;
@import "bootstrap/scss/bootstrap";
@use "bootstrap/scss/bootstrap" with (
$color-mode-type: media-query,
$font-family-sans-serif: ("FiraGO", system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"),
);
@import "@fontsource/firago/400.css";
@import "@fontsource/firago/400-italic.css";

View file

@ -3,9 +3,9 @@ import { Nav, Navbar } from "react-bootstrap";
import { Link } from "@remix-run/react";
import Logo from "~/components/nav/Logo";
export default function BaseNavbar({ children, theme }: { children?: ReactNode; theme: string }) {
export default function BaseNavbar({ children }: { children?: ReactNode; }) {
return (
<Navbar expand="lg" className={`mb-4 mx-2 bg-${theme}`} color={theme} variant={theme}>
<Navbar expand="lg" className={`mb-4 mx-2`}>
<Navbar.Brand to="/" as={Link}>
<Logo />
</Navbar.Brand>

View file

@ -1,19 +1,16 @@
import { Link, useFetcher } from "@remix-run/react";
import Meta from "~/lib/api/meta";
import { User, UserSettings } from "~/lib/api/user";
import { User } from "~/lib/api/user";
import { Nav, NavDropdown } from "react-bootstrap";
import { BrightnessHigh, BrightnessHighFill, MoonFill } from "react-bootstrap-icons";
import { useTranslation } from "react-i18next";
import BaseNavbar from "~/components/nav/BaseNavbar";
export default function MainNavbar({
user,
settings,
}: {
meta: Meta;
user?: User;
settings: UserSettings;
}) {
const fetcher = useFetcher();
const { t } = useTranslation();
@ -38,39 +35,10 @@ export default function MainNavbar({
{t("navbar.log-in")}
</Nav.Link>
);
const ThemeIcon =
settings.dark_mode === null
? BrightnessHigh
: settings.dark_mode
? MoonFill
: BrightnessHighFill;
const theme = settings.dark_mode ? "dark" : "light";
return (
<BaseNavbar theme={theme}>
<BaseNavbar>
{userMenu}
<fetcher.Form method="POST" action="/dark-mode">
<NavDropdown
title={
<>
<ThemeIcon /> {t("navbar.theme")}
</>
}
align="end"
>
<NavDropdown.Item as="button" name="theme" value="auto" type="submit">
{t("navbar.theme-auto")}
</NavDropdown.Item>
<NavDropdown.Item as="button" name="theme" value="dark" type="submit">
{t("navbar.theme-dark")}
</NavDropdown.Item>
<NavDropdown.Item as="button" name="theme" value="light" type="submit">
{t("navbar.theme-light")}
</NavDropdown.Item>
</NavDropdown>
</fetcher.Form>
</BaseNavbar>
);
}

View file

@ -57,7 +57,7 @@ export const loader = async ({ request }: LoaderFunctionArgs) => {
};
export function Layout({ children }: { children: ReactNode }) {
const { locale, settings } = useRouteLoaderData<typeof loader>("root") || {
const { locale } = useRouteLoaderData<typeof loader>("root") || {
meta: {
users: {
total: 0,
@ -77,7 +77,6 @@ export function Layout({ children }: { children: ReactNode }) {
return (
<html
lang={locale || "en"}
data-bs-theme={settings?.dark_mode ? "dark" : "light"}
dir={i18n.dir()}
>
<head>
@ -119,10 +118,10 @@ export function ErrorBoundary() {
<Links />
</head>
<body>
{data?.meUser && data?.settings && data?.meta ? (
<Navbar meta={data.meta} user={data.meUser} settings={data.settings} />
{data?.meUser && data?.meta ? (
<Navbar meta={data.meta} user={data.meUser} />
) : (
<BaseNavbar theme="light" />
<BaseNavbar />
)}
<Container>{errorElem}</Container>
<Scripts />

View file

@ -13,7 +13,7 @@ import PronounLink from "~/components/PronounLink";
export const meta: MetaFunction<typeof loader> = ({ data }) => {
const { user } = data!;
return [{ title: `@${user.username} - pronouns.cc` }];
return [{ title: `@${user.username} pronouns.cc` }];
};
export const loader = async ({ request, params }: LoaderFunctionArgs) => {

View file

@ -21,7 +21,7 @@ import ErrorAlert from "~/components/ErrorAlert";
import i18n from "~/i18next.server";
export const meta: MetaFunction<typeof loader> = ({ data }) => {
return [{ title: `${data?.meta.title || "Log in"} - pronouns.cc` }];
return [{ title: `${data?.meta.title || "Log in"} pronouns.cc` }];
};
export const shouldRevalidate: ShouldRevalidateFunction = ({ actionResult }) => {

View file

@ -21,7 +21,7 @@ import ErrorAlert from "~/components/ErrorAlert";
import { User } from "~/lib/api/user";
export const meta: MetaFunction<typeof loader> = ({ data }) => {
return [{ title: `${data?.meta.title || "Log in"} - pronouns.cc` }];
return [{ title: `${data?.meta.title || "Log in"} pronouns.cc` }];
};
export const shouldRevalidate: ShouldRevalidateFunction = ({ actionResult }) => {

View file

@ -7,7 +7,7 @@ import { Link, useLoaderData } from "@remix-run/react";
import { Button } from "react-bootstrap";
export const meta: MetaFunction<typeof loader> = ({ data }) => {
return [{ title: `${data?.meta.title || "Welcome"} - pronouns.cc` }];
return [{ title: `${data?.meta.title || "Welcome"} pronouns.cc` }];
};
export const loader = async ({ request }: LoaderFunctionArgs) => {

View file

@ -4,6 +4,13 @@ import serverRequest, { getCookie, writeCookie } from "~/lib/request.server";
// Handles theme switching
// Remix itself handles redirecting back to the original page after the setting is set
//
// Note: this function is currently unused. Bootstrap only lets us switch themes with either prefers-color-scheme
// *or* a programmatic switch using data-bs-theme, not both.
// If the Sec-CH-Prefers-Color-Scheme header (https://caniuse.com/mdn-http_headers_sec-ch-prefers-color-scheme)
// is added to Firefox and Safari, the dark mode setting should be reworked to use it instead.
// As it stands, using prefers-color-scheme is the only way
// to respect the operating system's dark mode setting without using JavaScript.
export const action: ActionFunction = async ({ request }) => {
const body = await request.formData();
const theme = (body.get("theme") as string | null) || "auto";
@ -13,7 +20,7 @@ export const action: ActionFunction = async ({ request }) => {
await serverRequest<UserSettings>("PATCH", "/users/@me/settings", {
token,
body: {
dark_mode: theme === "auto" ? null : theme === "dark" ? true : false,
dark_mode: theme === "auto" ? null : theme === "dark",
},
});