Theme briefly flashes light mode
- [x] I have searched the Issues to see if this bug has already been reported
- [x] I have tested the latest version
Steps to reproduce
- Refresh the page
Current behavior
The theme briefly shows as light mode if in dark mode and then flicks to the expected mode (dark). This doesn't happen in light mode.
Expected behavior
No flash when in dark mode like it does in light mode
Context
I'm using this in my layout:
<Flowbite>
<Head title={`${title} - ${app.name}`} />
{children}
</Flowbite>
I use Laravel/InertiaJS/React
Has anyone else experienced this or know how to resolve it?
Here is a video.
https://github.com/user-attachments/assets/9b2c1a84-e6ff-4779-a26d-702a58cd3df1
To fix this problem u'd have to persist in cache or Laravel session the mode.
I'll do a spike on implementing ThemeModeScript (see
https://flowbite-react.com/docs/guides/remix#dark-mode) that will take this off users shoulder.
To fix this problem u'd have to persist in cache or Laravel session the
mode.I'll do a spike on implementing
ThemeModeScript(see https://flowbite-react.com/docs/guides/remix#dark-mode) that will take this off users shoulder.
Thanks for replying.
So I should just store the choice in cache and then use useThemeMode() to set the theme or am I misunderstanding?
To fix this problem u'd have to persist in cache or Laravel session the
mode.I'll do a spike on implementing
ThemeModeScript(see https://flowbite-react.com/docs/guides/remix#dark-mode) that will take this off users shoulder.
To fix this problem u'd have to persist in cache or Laravel session the
mode. I'll do a spike on implementingThemeModeScript(see https://flowbite-react.com/docs/guides/remix#dark-mode) that will take this off users shoulder.Thanks for replying.
So I should just store the choice in cache and then use
useThemeMode()to set the theme or am I misunderstanding?
Or do you have a basic example? Happy to sponser you.
@harrisonratcliffe are u using Laravite + Vite + SSR mode? (check 1. https://laravel.com/docs/11.x/vite#ssr, 2. https://inertiajs.com/server-side-rendering)
@harrisonratcliffe are u using Laravite + Vite + SSR mode? (check 1. https://laravel.com/docs/11.x/vite#ssr, 2. https://inertiajs.com/server-side-rendering)
Yep I am using InertiaJS SSR.
After many failures, it seems so hard to inject JSX to HTML on-the-fly before page load with Inertia + SSR, which leaves us with one last option (dirty and will be deprecated in the future due to #1498 ):
open resources/views/app.blade.php page and inject the following script inside the head
<script data-flowbite-theme-mode-script>
try {
const mode = window.localStorage.getItem("flowbite-theme-mode") ?? "light";
const computedMode =
mode === "auto" ? (window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light") : mode;
if (computedMode === "dark") {
document.documentElement.classList.add("dark");
} else {
document.documentElement.classList.remove("dark");
}
} catch (e) {}
</script>
^ this is exactly what <ThemeModeScript /> renders at the moment
Ok, I've just found this when trying to resolve the white flicker when in dark mode and discovered the <ThemeModeScript /> component which has resolved the issue for me. Remix SSR. Searching the docs I found it on the Remix page which makes sense, must have missed it when I set the project up. Thanks and leaving this here for anyone else in future.
After many failures, it seems so hard to inject JSX to HTML on-the-fly before page load with Inertia + SSR, which leaves us with one last option (dirty and will be deprecated in the future due to #1498 ):
open
resources/views/app.blade.phppage and inject the following script inside thehead<script data-flowbite-theme-mode-script> try { const mode = window.localStorage.getItem("flowbite-theme-mode") ?? "light"; const computedMode = mode === "auto" ? (window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light") : mode; if (computedMode === "dark") { document.documentElement.classList.add("dark"); } else { document.documentElement.classList.remove("dark"); } } catch (e) {} </script>^ this is exactly what
<ThemeModeScript />renders at the moment
I still get the flashing with this fix when using Inertia SSR. Is this still the correct fix?
After many failures, it seems so hard to inject JSX to HTML on-the-fly before page load with Inertia + SSR, which leaves us with one last option (dirty and will be deprecated in the future due to #1498 ): open
resources/views/app.blade.phppage and inject the following script inside thehead<script data-flowbite-theme-mode-script> try { const mode = window.localStorage.getItem("flowbite-theme-mode") ?? "light"; const computedMode = mode === "auto" ? (window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light") : mode; if (computedMode === "dark") { document.documentElement.classList.add("dark"); } else { document.documentElement.classList.remove("dark"); } } catch (e) {} </script>^ this is exactly what
<ThemeModeScript />renders at the momentI still get the flashing with this fix when using Inertia SSR. Is this still the correct fix?
I did not use the flowbite but this fix my issue when using inertia ssr. make sure the localstorage key is the same.
Quick update:
The latest release includes a new function called initThemeMode() which can be called inside app.tsx of inertia and it will take care of this flashing issue caused by the delayed setting of .dark theme on <html>.
example:
import '../css/app.css';
import { createInertiaApp } from '@inertiajs/react';
import { initThemeMode } from 'flowbite-react';
import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers';
import { createRoot } from 'react-dom/client';
const appName = import.meta.env.VITE_APP_NAME || 'Laravel';
createInertiaApp({
title: (title) => `${title} - ${appName}`,
resolve: (name) => resolvePageComponent(`./pages/${name}.tsx`, import.meta.glob('./pages/**/*.tsx')),
setup({ el, App, props }) {
const root = createRoot(el);
root.render(<App {...props} />);
},
progress: {
color: '#4B5563',
},
});
// This will set light / dark mode on load...
initThemeMode();
Quick update:
The latest release includes a new function called
initThemeMode()which can be called insideapp.tsxof inertia and it will take care of this flashing issue caused by the delayed setting of.darktheme on<html>.example:
import '../css/app.css';
import { createInertiaApp } from '@inertiajs/react'; import { initThemeMode } from 'flowbite-react'; import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers'; import { createRoot } from 'react-dom/client';
const appName = import.meta.env.VITE_APP_NAME || 'Laravel';
createInertiaApp({ title: (title) =>
${title} - ${appName}, resolve: (name) => resolvePageComponent(./pages/${name}.tsx, import.meta.glob('./pages/**/*.tsx')), setup({ el, App, props }) { const root = createRoot(el);root.render(<App {...props} />); }, progress: { color: '#4B5563', },});
// This will set light / dark mode on load... initThemeMode();
This is great if it works, thank you.
However, I am getting the following error:
✘ [ERROR] Could not resolve "tailwindcss/version.js"
node_modules/flowbite-react/dist/helpers/get-tailwind-version.js:1:20:
1 │ import version from 'tailwindcss/version.js';
╵ ~~~~~~~~~~~~~~~~~~~~~~~~
You can mark the path "tailwindcss/version.js" as external to exclude it from the bundle, which
will remove this error and leave the unresolved path in the bundle.
@harrisonratcliffe it's because u did not properly install flowbite-react, please check the release note, Migration Guide section
@harrisonratcliffe it's because u did not properly install
flowbite-react, please check the release note, Migration Guide section![]()
I've just that which just breaks the entire site:
Uncaught SyntaxError: The requested module 'https://vite.dev.test/node_modules/.vite/deps/flowbite-react.js?v=72c9583e' doesn't provide an export named: 'Flowbite' [MasterLayout.tsx:26:10](https://vite.dev.test/resources/js/Layouts/MasterLayout.tsx?t=1743007851324)
Uncaught (in promise) SyntaxError: The requested module 'https://vite.dev.test/node_modules/.vite/deps/flowbite-react.js?v=72c9583e' doesn't provide an export named: 'Flowbite'
Master layout:
import { Flowbite, Toast, ToastToggle } from 'flowbite-react';
<Flowbite theme={{ theme }}>
code here
</Flowbite>
If I check other files like my navbar:
<Navigation.Brand>
<Link href={route('home')} className="flex items-center">
<img
src="/logo.webp"
className="mr-3 h-6 sm:h-9"
alt={`${app.name} Logo`}
/>
<span className="text-md self-center whitespace-nowrap font-semibold dark:text-gray-100 sm:text-xl">
{app.name}
</span>
</Link>
</Navigation.Brand>
TS2339: Property Brand does not exist on type
Those are just some examples, its every flowbite component.
@harrisonratcliffe it's because u did not properly install
flowbite-react, please check the release note, Migration Guide sectionI've just that which just breaks the entire site:
Uncaught SyntaxError: The requested module 'https://vite.dev.test/node_modules/.vite/deps/flowbite-react.js?v=72c9583e' doesn't provide an export named: 'Flowbite' [MasterLayout.tsx:26:10](https://vite.dev.test/resources/js/Layouts/MasterLayout.tsx?t=1743007851324) Uncaught (in promise) SyntaxError: The requested module 'https://vite.dev.test/node_modules/.vite/deps/flowbite-react.js?v=72c9583e' doesn't provide an export named: 'Flowbite'Master layout:
import { Flowbite, Toast, ToastToggle } from 'flowbite-react'; <Flowbite theme={{ theme }}> code here </Flowbite>If I check other files like my navbar:
<Navigation.Brand> <Link href={route('home')} className="flex items-center"> <img src="/logo.webp" className="mr-3 h-6 sm:h-9" alt={`${app.name} Logo`} /> <span className="text-md self-center whitespace-nowrap font-semibold dark:text-gray-100 sm:text-xl"> {app.name} </span> </Link> </Navigation.Brand>
TS2339: Property Brand does not exist on typeThose are just some examples, its very flowbite component.
Ok so I see a lot of the components have been renamed. I think everything is working now.
Thanks so much.
@harrisonratcliffe that is why we have the npx flowbite-react@latest migrate command, to help out with compound components renaming.
Happy that it worked.
@harrisonratcliffe that is why we have the
npx flowbite-react@latest migratecommand, to help out with compound components renaming.Happy that it worked.
I did run the migrate command but it seems a lot of files were ignored due to: Warning: Could not parse file, skipping transformation
Some typescript files are hard to parse as AST, resulting in skipping them in favor of not crashing the entire process. Improvements will be made.
Is anyone else still experiencing this issue? I am still seeing a flash.
@harrisonratcliffe did u call initThemeMode() immediately after createInertiaApp({...}) in app.tsx?
@harrisonratcliffe did u call
initThemeMode()immediately aftercreateInertiaApp({...})inapp.tsx?
Yes:
import '../css/app.css';
import './bootstrap';
import { createInertiaApp } from '@inertiajs/react';
import { initThemeMode } from 'flowbite-react';
import TimeAgo from 'javascript-time-ago';
import en from 'javascript-time-ago/locale/en';
import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers';
import { createRoot, hydrateRoot } from 'react-dom/client';
TimeAgo.addDefaultLocale(en);
TimeAgo.addLocale(en);
createInertiaApp({
title: (title) => `${title} - ${import.meta.env.VITE_APP_NAME}`,
resolve: (name) => {
const pages = import.meta.glob('./Pages/**/*.tsx');
return resolvePageComponent(`./Pages/${name}.tsx`, pages);
},
setup({ el, App, props }) {
if (import.meta.env.SSR) {
hydrateRoot(el, <App {...props} />);
}
createRoot(el).render(<App {...props} />);
},
progress: {
color: '#3b82f6',
},
});
initThemeMode();
What version of laravel, inertia and vite are u having?
"@inertiajs/react": "^2.0.2",
"typescript": "^5.6.3",
"vite": "^5.0",
"laravel/framework": "^11.9",