preline icon indicating copy to clipboard operation
preline copied to clipboard

Unable to use Preline Examples in Remix App

Open dhavalveera opened this issue 1 year ago • 3 comments

Hello,

I wanted to use Features Nav in my Remix App, and for that I tried to follow this Installation Steps but unfortunately I was failed to use it.

I am able to render the UI exactly as it's Tailwind CSS, but the functionality, I am not able to make it, can anyone help me where I am doing the mistake?

dhavalveera avatar Mar 28 '24 01:03 dhavalveera

I was facing the same problem. Current installation steps are invalid for Remix 2.8.1.

I managed to fix the problem:

  1. Install preline npm install preline

  2. Add the path to Preline UI JavaScript files in your tailwind.config.js file.

// tailwind.config.js
module.exports = {
  content: [
      './node_modules/preline/preline.js',
  ],
  plugins: [
      require('preline/plugin'),
  ],
}
  1. Create preline.client.tsx file for example in ~/components folder. (We will use client module):
import {
    useLocation,
} from "@remix-run/react";
import { useEffect } from "react";

import { IStaticMethods } from "preline/preline";
declare global {
    interface Window {
        HSStaticMethods: IStaticMethods;
    }
}

export default function PrelineScript() {
    const location = useLocation();

    useEffect(() => {
        import("preline/preline");
    }, []);

    useEffect(() => {
        setTimeout(() => {
            window.HSStaticMethods.autoInit();
        }, 100);
    }, [location.pathname]);

    return null;
}
  1. Connect this file in root.tsx:
...
// Import at top of file
import PrelineScript from "~/components/preline.client";

export function Layout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <head>
        <meta charSet="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <Meta />
        <Links />
      </head>
      <body>
        {children}
        <ScrollRestoration />
        <Scripts />
        {/* Add preline script on every page */}
        {PrelineScript && <PrelineScript />}
      </body>
    </html>
  );
}

...

AlexBSoft avatar Mar 29 '24 18:03 AlexBSoft

`declare global { interface Window { HSStaticMethods: IStaticMethods; } } if (typeof window !== "undefined") { await import('preline/preline'); }

export function Layout({ children }: { children: ReactNode }) { const location = useLocation();

useEffect(() => { window.HSStaticMethods.autoInit(); }, [location.pathname]);

return ( ... ) `

Replace typeof window !== "undefined" with typeof document !== "undefined" to handle runtimes outside of Node like Deno. Read the Remix Gotchas for more info.

bluefire2121 avatar Mar 31 '24 23:03 bluefire2121

The suggestion above (could) cause(s) a FOUC, this suggestion does not: https://github.com/htmlstreamofficial/preline/issues/350#issuecomment-2241599171

bravo-kernel avatar Aug 11 '24 14:08 bravo-kernel

Thanks for sharing your workarounds. We've added a link to this page in our docs under Community Workarounds.

jahaganiev avatar Nov 01 '24 16:11 jahaganiev

This guide provides step-by-step instructions for installing Preline in a project using Remix and React Router .v7, as well as integrating an initialization component for Preline’s static methods.

Step 1: Install Required Dependencies

  • npm install preline

Step 2: Add the Preline UI plugin

  • Include Preline UI as a plugin in the tailwind.config.js file.
 module.exports = { 
     content: [   
     
      "node_modules/preline/dist/*.js",  ], 
    
     plugins: [  
    
       require('preline/plugin'),  
    
    ],
}



Step 3: Add the Preline UI JavaScript

Copy Necessary Scripts:

  • Create a folder named scripts inside the public directory of your Remix or React Router project. This ensures the scripts will be available after the build process.

Add Required Libraries:

  • Copy the libraries (e.g., lodash.min.js, dropzone.min.js) from node_modules to public/scripts.

Step 4: Create the Preline Initialization Component

  • Create a new file app/components/PrelineInit.tsx and add the following:
import { useLocation } from "react-router";
import { useEffect } from "react";

import type { IStaticMethods } from "preline/preline";
declare global {
  interface Window {
    HSStaticMethods: IStaticMethods;
  }
}

export default function PrelineInit() {
  const location = useLocation();

  useEffect(() => {
    import("preline/preline").then(() => {
      window.HSStaticMethods?.autoInit();
    });
  }, [location.pathname]);

  return null;
}

Step 4: Update the Root File

 <script src="/scripts/lodash.min.js"></script>

 <script src="/scripts/dropzone.min.js"></script>

{ PrelineInit && <PrelineInit /> } 


import {
  isRouteErrorResponse,
  Links,
  Meta,
  Outlet,
  Scripts,
  ScrollRestoration,
} from "react-router";

import type { Route } from "./+types/root";
import stylesheet from "./app.css?url";
import PrelineInit from "./components/ui/PrelineInit";

export const links: Route.LinksFunction = () => [
  { rel: "preconnect", href: "https://fonts.googleapis.com" },
  {
    rel: "preconnect",
    href: "https://fonts.gstatic.com",
    crossOrigin: "anonymous",
  },
  {
    rel: "stylesheet",
    href: "https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap",
  },
  { rel: "stylesheet", href: stylesheet },
];

export function Layout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <head>
        <meta charSet="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <Meta />
        <Links />
        <script src="/scripts/lodash.min.js"></script>
        <script src="/scripts/dropzone.min.js"></script>
      </head>
      <body>
        {children}
        <ScrollRestoration />
        <Scripts />
        {PrelineInit && <PrelineInit />}
      </body>
    </html>
  );
}

export default function App() {
  return <Outlet />;
}

export function ErrorBoundary({ error }: Route.ErrorBoundaryProps) {
  let message = "Oops!";
  let details = "An unexpected error occurred.";
  let stack: string | undefined;

  if (isRouteErrorResponse(error)) {
    message = error.status === 404 ? "404" : "Error";
    details =
      error.status === 404
        ? "The requested page could not be found."
        : error.statusText || details;
  } else if (import.meta.env.DEV && error && error instanceof Error) {
    details = error.message;
    stack = error.stack;
  }

  return (
    <main className="pt-16 p-4 container mx-auto">
      <h1>{message}</h1>
      <p>{details}</p>
      {stack && (
        <pre className="w-full p-4 overflow-x-auto">
          <code>{stack}</code>
        </pre>
      )}
    </main>
  );
}


Step 5: Verify Setup

  • npm run dev

    Ensure all scripts load correctly by inspecting the browser’s network tab.

**Step 6: Build your project to verify the setup:

  • npm run build
  • npm run start

Additional Notes • Why Use public/scripts: Placing scripts in public/scripts ensures they are served properly and included in the final build. • Fonts and Stylesheets: Ensure fonts and stylesheets are correctly linked in the links function to avoid styling issues.

This completes the setup of Preline with React Router .v7 and Remix.

sbeckerdev avatar Jan 02 '25 02:01 sbeckerdev

@jahaganiev Can you update the preline community guide? This is the workaround for React Router .v7 and Remix. Thank you.

sbeckerdev avatar Jan 02 '25 02:01 sbeckerdev

Hello,

I wanted to use Features Nav in my Remix App, and for that I tried to follow this Installation Steps but unfortunately I was failed to use it.

I am able to render the UI exactly as it's Tailwind CSS, but the functionality, I am not able to make it, can anyone help me where I am doing the mistake?

I have added a complete workaround for React Router .v7 and Remix. Please have a look at it.

sbeckerdev avatar Jan 02 '25 02:01 sbeckerdev

Hey @sbeckerdev - thanks for the input, appreciate it much! Our team will check out in details.

Just for the side info, this issue thread has a link on the live docs.

jahaganiev avatar Jan 02 '25 02:01 jahaganiev

Hey @sbeckerdev - thanks for the input, appreciate it much! Our team will check out in details.

Just for the side info, this issue thread has a link on the live docs.

You are welcome!

sbeckerdev avatar Jan 02 '25 02:01 sbeckerdev