flowbite-react icon indicating copy to clipboard operation
flowbite-react copied to clipboard

Theme briefly flashes light mode

Open harrisonratcliffe opened this issue 1 year ago • 23 comments

  • [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

  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 avatar Nov 06 '24 17:11 harrisonratcliffe

Here is a video.

https://github.com/user-attachments/assets/9b2c1a84-e6ff-4779-a26d-702a58cd3df1

harrisonratcliffe avatar Nov 06 '24 17:11 harrisonratcliffe

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.

SutuSebastian avatar Nov 06 '24 18:11 SutuSebastian

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 avatar Nov 06 '24 18:11 harrisonratcliffe

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.

harrisonratcliffe avatar Nov 06 '24 19:11 harrisonratcliffe

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

SutuSebastian avatar Nov 07 '24 07:11 SutuSebastian

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

harrisonratcliffe avatar Nov 07 '24 07:11 harrisonratcliffe

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

SutuSebastian avatar Nov 07 '24 08:11 SutuSebastian

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.

jonyboom avatar Nov 16 '24 18:11 jonyboom

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?

harrisonratcliffe avatar Jan 15 '25 17:01 harrisonratcliffe

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.

ssatriya avatar Feb 07 '25 05:02 ssatriya

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

SutuSebastian avatar Mar 26 '25 10:03 SutuSebastian

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.

harrisonratcliffe avatar Mar 26 '25 15:03 harrisonratcliffe

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

Image

SutuSebastian avatar Mar 26 '25 16:03 SutuSebastian

@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 avatar Mar 26 '25 16:03 harrisonratcliffe

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

harrisonratcliffe avatar Mar 26 '25 17:03 harrisonratcliffe

@harrisonratcliffe that is why we have the npx flowbite-react@latest migrate command, to help out with compound components renaming.

Happy that it worked.

SutuSebastian avatar Mar 26 '25 17:03 SutuSebastian

@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

harrisonratcliffe avatar Mar 26 '25 17:03 harrisonratcliffe

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.

SutuSebastian avatar Mar 26 '25 17:03 SutuSebastian

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

harrisonratcliffe avatar Mar 27 '25 11:03 harrisonratcliffe

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

SutuSebastian avatar Mar 27 '25 12:03 SutuSebastian

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

harrisonratcliffe avatar Mar 27 '25 12:03 harrisonratcliffe

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

SutuSebastian avatar Mar 27 '25 12:03 SutuSebastian

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

harrisonratcliffe avatar Mar 27 '25 12:03 harrisonratcliffe