Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Theme briefly flashes light mode #1506

Open
2 tasks done
harrisonratcliffe opened this issue Nov 6, 2024 · 23 comments
Open
2 tasks done

Theme briefly flashes light mode #1506

harrisonratcliffe opened this issue Nov 6, 2024 · 23 comments

Comments

@harrisonratcliffe
Copy link

harrisonratcliffe commented Nov 6, 2024

  • I have searched the Issues to see if this bug has already been reported
  • I have tested the latest version

Steps to reproduce

  1. 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?

@harrisonratcliffe
Copy link
Author

Here is a video.

Screen.Recording.2024-11-06.at.17.47.53.mov

@SutuSebastian
Copy link
Collaborator

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.

@harrisonratcliffe
Copy link
Author

harrisonratcliffe commented Nov 6, 2024

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?

@harrisonratcliffe
Copy link
Author

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?

Or do you have a basic example? Happy to sponser you.

@SutuSebastian
Copy link
Collaborator

@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
Copy link
Author

@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.

@SutuSebastian
Copy link
Collaborator

SutuSebastian commented Nov 7, 2024

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

@jonyboom
Copy link

Ok, I've just found this when trying to resolve the white flicker when in dark mode and discovered the 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.

@harrisonratcliffe
Copy link
Author

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

I still get the flashing with this fix when using Inertia SSR. Is this still the correct fix?

@ssatriya
Copy link

ssatriya commented Feb 7, 2025

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

I 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.

@SutuSebastian
Copy link
Collaborator

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();

@harrisonratcliffe
Copy link
Author

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();

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.

@SutuSebastian
Copy link
Collaborator

@harrisonratcliffe it's because u did not properly install flowbite-react, please check the release note, Migration Guide section

Image

@harrisonratcliffe
Copy link
Author

harrisonratcliffe commented Mar 26, 2025

@harrisonratcliffe it's because u did not properly install flowbite-react, please check the release note, Migration Guide section

Image

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
Copy link
Author

@harrisonratcliffe it's because u did not properly install flowbite-react, please check the release note, Migration Guide section
Image

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 very flowbite component.

Ok so I see a lot of the components have been renamed. I think everything is working now.

Thanks so much.

@SutuSebastian
Copy link
Collaborator

@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
Copy link
Author

@harrisonratcliffe that is why we have the npx flowbite-react@latest migrate command, 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

@SutuSebastian
Copy link
Collaborator

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.

@harrisonratcliffe
Copy link
Author

Is anyone else still experiencing this issue? I am still seeing a flash.

@SutuSebastian
Copy link
Collaborator

@harrisonratcliffe did u call initThemeMode() immediately after createInertiaApp({...}) in app.tsx?

@harrisonratcliffe
Copy link
Author

@harrisonratcliffe did u call initThemeMode() immediately after createInertiaApp({...}) in app.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();

@SutuSebastian
Copy link
Collaborator

What version of laravel, inertia and vite are u having?

@SutuSebastian SutuSebastian reopened this Mar 27, 2025
@harrisonratcliffe
Copy link
Author

"@inertiajs/react": "^2.0.2",
"typescript": "^5.6.3",
"vite": "^5.0",
"laravel/framework": "^11.9",

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants