Learn how to set up Material Tailwind with Remix. This guide will walk you through installation, configuration, and basic usage.
Start by creating a new Remix project and installing the required dependencies:
1npx create-remix@latest
2npm install -D tailwindcss postcss autoprefixer
3npx tailwindcss init -p
Update the content paths in your tailwind.config.js
or tailwind.config.ts
:
1// For JavaScript (tailwind.config.js)
2/** @type {import('tailwindcss').Config} */
3module.exports = {
4content: [
5 "./app/**/*.{js,jsx,ts,tsx}",
6],
7theme: {
8 extend: {},
9},
10plugins: [],
11}
12
13// For TypeScript (tailwind.config.ts)
14import type { Config } from 'tailwindcss'
15
16export default {
17content: [
18 "./app/**/*.{js,jsx,ts,tsx}",
19],
20theme: {
21 extend: {},
22},
23plugins: [],
24} satisfies Config
Create a new CSS file in app/styles/tailwind.css
and add the Tailwind directives:
1@tailwind base;
2@tailwind components;
3@tailwind utilities;
Import the styles in your app/root.tsx
:
1import type { LinksFunction } from "@remix-run/node";
2import styles from "~/styles/tailwind.css";
3
4export const links: LinksFunction = () => [
5{ rel: "stylesheet", href: styles }
6];
7
8export default function App() {
9return (
10 <html lang="en">
11 <head>
12 <Meta />
13 <Links />
14 </head>
15 <body>
16 <Outlet />
17 <ScrollRestoration />
18 <Scripts />
19 <LiveReload />
20 </body>
21 </html>
22);
23}
Install @material-tailwind/html:
1npm i @material-tailwind/html
Here's how to use Material Tailwind components in your Remix routes:
1// app/routes/_index.tsx
2import { useEffect } from "react";
3import { useHydrated } from "@remix-run/react";
4import { initAccordion } from "@material-tailwind/html"; // ESM & CJS
5
6export default function Index() {
7const isHydrated = useHydrated();
8
9useEffect(() => {
10 if (isHydrated) {
11 initAccordion();
12 }
13}, [isHydrated]);
14
15return (
16 <div className="w-full">
17 <div className="group block w-full" data-accordion-container data-accordion-mode="exclusive">
18 <button
19 data-accordion-toggle
20 data-accordion-target="#accordion-1"
21 aria-expanded="false"
22 className="flex w-full items-center justify-between p-4 text-left"
23 >
24 <span>What is Material Tailwind?</span>
25 <svg
26 data-accordion-icon
27 className="h-5 w-5 rotate-0 transition-transform"
28 fill="none"
29 stroke="currentColor"
30 viewBox="0 0 24 24"
31 xmlns="http://www.w3.org/2000/svg"
32 >
33 <path
34 strokeLinecap="round"
35 strokeLinejoin="round"
36 strokeWidth="2"
37 d="M19 9l-7 7-7-7"
38 ></path>
39 </svg>
40 </button>
41 <div
42 id="accordion-1"
43 className="overflow-hidden transition-all duration-300"
44 >
45 <div className="p-4">
46 <p>
47 Material Tailwind is an easy to use components library for Tailwind CSS.
48 </p>
49 </div>
50 </div>
51 </div>
52 </div>
53);
54}
For TypeScript projects, you can use the typed interfaces and configurations:
1// app/components/Accordion.tsx
2import { useEffect } from "react";
3import { useHydrated } from "@remix-run/react";
4import { Accordion } from "@material-tailwind/html";
5import type { AccordionConfig } from "@material-tailwind/html";
6
7export default function AccordionExample() {
8const isHydrated = useHydrated();
9
10useEffect(() => {
11 if (isHydrated) {
12 const container = document.getElementById("accordion-container");
13
14 if (container) {
15 const config: AccordionConfig = {
16 exclusive: true,
17 allOpen: false,
18 };
19
20 new Accordion(container, config);
21 }
22 }
23}, [isHydrated]);
24
25return (
26 <div id="accordion-container" className="group block w-full">
27 <div
28 className="flex items-center justify-between w-full py-5 text-left font-medium dark:text-white text-slate-800 cursor-pointer"
29 aria-expanded="false"
30 id="button-1">
31 Material Tailwind React
32 <svg data-accordion-icon width="1.5em" height="1.5em" strokeWidth="1.5" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" color="currentColor" className="h-4 w-4 transition-transform duration-300 rotate-180">
33 <path d="M6 9L12 15L18 9" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round"></path>
34 </svg>
35 </div>
36 <div id="button-1" className="overflow-hidden transition-all duration-300 border-b border-slate-200 dark:border-slate-700">
37 <p className="mb-5 text-sm text-slate-600 dark:text-slate-400">Material Tailwind is an open-source library crafted with Tailwind CSS. Get Material Tailwind and take advantage of its free components and features.</p>
38 </div>
39
40 <div
41 className="flex items-center justify-between w-full py-5 text-left font-medium dark:text-white text-slate-800 cursor-pointer"
42 aria-expanded="false"
43 id="button-2">
44 Material Tailwind HTML
45 <svg data-accordion-icon width="1.5em" height="1.5em" strokeWidth="1.5" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" color="currentColor" className="h-4 w-4 transition-transform duration-300 rotate-180">
46 <path d="M6 9L12 15L18 9" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round"></path>
47 </svg>
48 </div>
49 <div id="button-2" className="overflow-hidden transition-all duration-300 border-b border-slate-200 dark:border-slate-700">
50 <p className="mb-5 text-sm text-slate-600 dark:text-slate-400">Material Tailwind is an open-source library crafted with Tailwind CSS. Get Material Tailwind and take advantage of its free components and features.</p>
51 </div>
52 </div>
53);
54}
For TypeScript projects, ensure your tsconfig.json
includes:
1{
2"compilerOptions": {
3 "moduleResolution": "node",
4},
5}
Note: The TypeScript configuration above includes Remix-specific settings to ensure proper type checking and module resolution when using Material Tailwind components.
Since Remix uses server-side rendering, make sure to initialize components after hydration:
1import { useHydrated } from "@remix-run/react";
2import { initAccordion } from "@material-tailwind/html";
3
4export default function Component() {
5const isHydrated = useHydrated();
6
7useEffect(() => {
8 if (isHydrated) {
9 initAccordion();
10 }
11}, [isHydrated]);
12
13return (
14 // Component content
15);
16}
Note: For more examples and detailed documentation of each component, check out the Accordion component.