Unable to use Preline Examples in Remix App
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 was facing the same problem. Current installation steps are invalid for Remix 2.8.1.
I managed to fix the problem:
-
Install preline
npm install preline -
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'),
],
}
- Create
preline.client.tsxfile 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;
}
- 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>
);
}
...
`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.
The suggestion above (could) cause(s) a FOUC, this suggestion does not: https://github.com/htmlstreamofficial/preline/issues/350#issuecomment-2241599171
Thanks for sharing your workarounds. We've added a link to this page in our docs under Community Workarounds.
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.
@jahaganiev Can you update the preline community guide? This is the workaround for React Router .v7 and Remix. Thank you.
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.
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.
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!