Skip to content

Commit efbd1ea

Browse files
committed
fix(react): Fix React dark mode variant
1 parent 2d29fe4 commit efbd1ea

File tree

8 files changed

+114
-44
lines changed

8 files changed

+114
-44
lines changed

examples/react/index.html

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@
2323
<title>Vite + React</title>
2424
</head>
2525
<body class="dark:bg-neutral-900 dark:text-white">
26+
<script>
27+
document.documentElement.classList.toggle("dark", localStorage.theme === "dark" || (!("theme" in localStorage) && window.matchMedia("(prefers-color-scheme: dark)").matches));
28+
</script>
2629
<div id="root"></div>
2730
<script type="module" src="/src/main.tsx"></script>
2831
<link rel="stylesheet" href="src/index.css">

examples/react/src/App.tsx

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ function UnauthenticatedApp() {
4040
Welcome to Firebase UI, choose an example screen below to get started!
4141
</p>
4242
</div>
43-
<div className="border border-neutral-800 rounded divide-y divide-neutral-800 overflow-hidden">
43+
<div className="border border-neutral-200 dark:border-neutral-800 rounded divide-y divide-neutral-200 dark:divide-neutral-800 overflow-hidden">
4444
{routes.map((route) => (
4545
<Link
4646
key={route.path}
@@ -51,7 +51,7 @@ function UnauthenticatedApp() {
5151
<h2 className="font-medium text-sm">{route.name}</h2>
5252
<p className="text-xs text-gray-400 dark:text-gray-300">{route.description}</p>
5353
</div>
54-
<div>
54+
<div className="text-neutral-600 dark:text-neutral-400">
5555
<span className="text-xl">&rarr;</span>
5656
</div>
5757
</Link>
@@ -68,27 +68,32 @@ function AuthenticatedApp() {
6868

6969
return (
7070
<div className="max-w-sm mx-auto pt-36 space-y-6 pb-36">
71-
<div className="border border-neutral-800 rounded p-4 space-y-4">
71+
<div className="border border-neutral-200 dark:border-neutral-800 rounded-md p-4 space-y-4">
7272
<h1 className="text-md font-medium">Welcome, {user.displayName || user.email || user.phoneNumber}</h1>
73-
{user.emailVerified ? (
74-
<div className="text-green-500">Email verified</div>
75-
) : (
76-
<button
77-
className="bg-red-500 text-white px-3 py-1.5 rounded text-sm"
78-
onClick={async () => {
79-
try {
80-
await sendEmailVerification(user);
81-
alert("Email verification sent, please check your email");
82-
} catch (error) {
83-
console.error(error);
84-
alert("Error sending email verification, check console");
85-
}
86-
}}
87-
>
88-
Verify Email &rarr;
89-
</button>
90-
)}
91-
<hr className="opacity-20" />
73+
{user.email ? (
74+
<>
75+
{user.emailVerified ? (
76+
<div className="text-green-500">Email verified</div>
77+
) : (
78+
<button
79+
className="bg-red-500 text-white px-3 py-1.5 rounded text-sm"
80+
onClick={async () => {
81+
try {
82+
await sendEmailVerification(user);
83+
alert("Email verification sent, please check your email");
84+
} catch (error) {
85+
console.error(error);
86+
alert("Error sending email verification, check console");
87+
}
88+
}}
89+
>
90+
Verify Email &rarr;
91+
</button>
92+
)}
93+
</>
94+
) : null}
95+
96+
<hr className="opacity-30" />
9297
<h2 className="text-sm font-medium">Multi-factor Authentication</h2>
9398
{mfa.enrolledFactors.map((factor) => {
9499
return (
@@ -105,7 +110,7 @@ function AuthenticatedApp() {
105110
>
106111
Add MFA Factor &rarr;
107112
</button>
108-
<hr className="opacity-20" />
113+
<hr className="opacity-30" />
109114
<button
110115
className="bg-blue-500 text-white px-3 py-1.5 rounded text-sm"
111116
onClick={async () => await signOut(auth)}

examples/react/src/firebase/firebase.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
import { initializeApp, getApps } from "firebase/app";
2020
import { firebaseConfig } from "./config";
21-
import { getAuth } from "firebase/auth";
21+
import { connectAuthEmulator, getAuth } from "firebase/auth";
2222
import { initializeUI, oneTapSignIn, countryCodes } from "@firebase-ui/core";
2323

2424
export const firebaseApp = getApps().length === 0 ? initializeApp(firebaseConfig) : getApps()[0];
@@ -40,6 +40,6 @@ export const ui = initializeUI({
4040
],
4141
});
4242

43-
// if (import.meta.env.MODE === "development") {
44-
// connectAuthEmulator(auth, "http://localhost:9099");
45-
// }
43+
if (import.meta.env.MODE === "development") {
44+
connectAuthEmulator(auth, "http://localhost:9099");
45+
}

examples/react/src/index.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616

1717
@import "tailwindcss";
18+
@custom-variant dark (&:where(.dark, .dark *));
1819
@import "@firebase-ui/styles/tailwind";
1920

2021
/* @import "@firebase-ui/styles/src/themes/dark.css"; */

examples/react/src/main.tsx

Lines changed: 57 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17-
import { BrowserRouter, Routes, Route } from "react-router";
17+
import { BrowserRouter, Routes, Route, Outlet, NavLink } from "react-router";
1818

1919
import ReactDOM from "react-dom/client";
2020
import { FirebaseUIProvider } from "@firebase-ui/react";
@@ -37,13 +37,66 @@ auth.authStateReady().then(() => {
3737
privacyPolicyUrl: "https://www.google.com",
3838
}}
3939
>
40+
<ThemeToggle />
4041
<Routes>
4142
<Route path="/" element={<App />} />
42-
{allRoutes.map((route) => (
43-
<Route key={route.path} path={route.path} element={<route.component />} />
44-
))}
43+
<Route element={<ScreenRoute />}>
44+
{allRoutes.map((route) => (
45+
<Route key={route.path} path={route.path} element={<route.component />} />
46+
))}
47+
</Route>
4548
</Routes>
4649
</FirebaseUIProvider>
4750
</BrowserRouter>
4851
);
4952
});
53+
54+
function ScreenRoute() {
55+
return (
56+
<div className="p-8">
57+
<NavLink
58+
to="/"
59+
className="border border-gray-300 dark:border-gray-700 border-rounded px-4 py-2 rounded-md text-sm"
60+
>
61+
&larr; Back to overview
62+
</NavLink>
63+
<div className="pt-12">
64+
<Outlet />
65+
</div>
66+
</div>
67+
);
68+
}
69+
70+
function ThemeToggle() {
71+
return (
72+
<button
73+
className="fixed z-10 top-8 right-8 border border-gray-300 dark:border-gray-700 rounded-md p-2 group/toggle extend-touch-target"
74+
onClick={() => {
75+
document.documentElement.classList.toggle("dark", !document.documentElement.classList.contains("dark"));
76+
localStorage.theme = document.documentElement.classList.contains("dark") ? "dark" : "light";
77+
}}
78+
title="Toggle theme"
79+
>
80+
<svg
81+
xmlns="http://www.w3.org/2000/svg"
82+
width="24"
83+
height="24"
84+
viewBox="0 0 24 24"
85+
fill="none"
86+
stroke="currentColor"
87+
strokeWidth="2"
88+
strokeLinecap="round"
89+
strokeLinejoin="round"
90+
className="size-4.5"
91+
>
92+
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
93+
<path d="M12 12m-9 0a9 9 0 1 0 18 0a9 9 0 1 0 -18 0" />
94+
<path d="M12 3l0 18" />
95+
<path d="M12 9l4.65 -4.65" />
96+
<path d="M12 14.3l7.37 -7.37" />
97+
<path d="M12 19.6l8.85 -8.85" />
98+
</svg>
99+
<span className="sr-only">Toggle theme</span>
100+
</button>
101+
);
102+
}

packages/react/src/auth/forms/multi-factor-auth-enrollment-form.tsx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,19 @@ export function MultiFactorAuthEnrollmentForm(props: MultiFactorAuthEnrollmentFo
5858
function TotpButton(props: ComponentProps<typeof Button>) {
5959
const ui = useUI();
6060
const labelText = getTranslation(ui, "labels", "mfaTotpVerification");
61-
return <Button {...props}>{labelText}</Button>;
61+
return (
62+
<Button variant="secondary" {...props}>
63+
{labelText}
64+
</Button>
65+
);
6266
}
6367

6468
function SmsButton(props: ComponentProps<typeof Button>) {
6569
const ui = useUI();
6670
const labelText = getTranslation(ui, "labels", "mfaSmsVerification");
67-
return <Button {...props}>{labelText}</Button>;
71+
return (
72+
<Button variant="secondary" {...props}>
73+
{labelText}
74+
</Button>
75+
);
6876
}

packages/react/src/auth/oauth/oauth-button.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ export function OAuthButton({ provider, children, themed }: OAuthButtonProps) {
5858
<div>
5959
<Button
6060
type="button"
61+
variant={themed ? "primary" : "secondary"}
6162
data-themed={themed}
6263
data-provider={provider.providerId}
6364
disabled={ui.state !== "idle"}

packages/styles/src/base.css

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -38,27 +38,26 @@
3838
--fui-radius: var(--radius-sm);
3939
/* The radius used for the cards */
4040
--fui-radius-card: var(--radius-xl);
41-
}
4241

43-
/* Apply dark mode styles when the dark variant is applied */
44-
/* See https://tailwindcss.com/docs/dark-mode */
45-
@variant dark {
46-
:root {
42+
/* Apply dark mode styles when the dark variant is applied */
43+
/* See https://tailwindcss.com/docs/dark-mode */
44+
@variant dark {
4745
--fui-primary: var(--color-white);
4846
--fui-primary-hover: --alpha(var(--fui-primary) / 85%);
4947
--fui-primary-surface: var(--color-black);
5048
--fui-text: var(--color-white);
51-
--fui-text-muted: var(--color-gray-200);
52-
--fui-background: var(--color-black);
53-
--fui-border: var(--color-gray-200);
54-
--fui-input: var(--color-gray-300);
55-
--fui-error: var(--color-red-500);
49+
--fui-text-muted: var(--color-neutral-300);
50+
--fui-background: var(--color-neutral-950);
51+
--fui-border: var(--color-neutral-800);
52+
--fui-input: var(--color-neutral-700);
53+
--fui-error: var(--color-red-700);
5654
--fui-radius: var(--radius-sm);
5755
--fui-radius-card: var(--radius-xl);
5856
}
5957
}
6058
}
6159

60+
6261
@theme {
6362
--color-primary: var(--fui-primary);
6463
--color-primary-hover: var(--fui-primary-hover);
@@ -76,7 +75,7 @@
7675
@layer components {
7776
/* Using :where() to reduce CSS specificity - allows users to easily override with their own Tailwind classes */
7877
:where(.fui-screen) {
79-
@apply pt-24 max-w-md mx-auto;
78+
@apply max-w-sm mx-auto;
8079
}
8180

8281
:where(.fui-screen .fui-screen__children) {

0 commit comments

Comments
 (0)