Using Tailwind v3 with shadcn/ui
Introduction
At the moment of writing, using Tailwind CSS v4 breaks Vite's Hot Module Replacement (HMR).
This guide walks you through setting up Tailwind CSS v3 and shadcn/ui in an Elmish Land project,.
Setting Up Tailwind CSS v3 in an Elmish Land Project
To use Tailwind CSS with Elmish Land, follow these steps:
1. Install Tailwind CSS v3
Install Tailwind CSS and its dependencies to your Elmish Land project (See Creating a project for information on how to create a new Elmish Land project), following the official docs:
npm install -D tailwindcss@3 postcss autoprefixer
npx tailwindcss init -p
2. Configure tailwind.config.js
Add the paths to all of your template files in your tailwind.config.js
file:
/** @type {import('tailwindcss').Config} */
export default {
content: [
"./index.html",
"./src/**/*.{js,ts,jsx,tsx}",
],
theme: {
extend: {},
},
plugins: [],
}
3. Add the Tailwind directives to your CSS
Create a file named styles.css
in the root folder of your project and add Tailwind directives.
@tailwind base;
@tailwind components;
@tailwind utilities;
4. Add your CSS file to index.html
Add a link to your styles.css
in the <head>
section of your index.html
.
<!DOCTYPE html>
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta charset="UTF-8">
<link href="/styles.css" rel="stylesheet">
<title>TailwindElmishLand</title>
</head>
<body>
<div id="app"></div>
<script type="module" src=".elmish-land/App/App.fs.js"></script>
</body>
</html>
This will setup Tailwind CSS v3. Follow the next step if you want to setup shadcn/ui.
Using shadcn/ui with Tailwind CSS v3
Following the official guide we need to use shadcn@2.3.0
.
1. Configure import alias in tsconfig
Create a file named tsconfig.json
in the root folder of your project and add the following:
{
"files": [],
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": [
"./src/*"
]
}
}
}
2. Configure Vite
Add the path
import and shadcn's component alias to your Vite configuration vite.config.js
:
import { defineConfig } from 'vite'
import path from "path"
export default defineConfig({
build: {
outDir: "dist"
},
resolve: {
alias: {
"@": path.resolve(__dirname, "./src"),
},
},
})
3. Install shadcn/ui
npx shadcn@2.3.0 init
You will be asked a few questions to configure components.json.
4. Add Feliz.Shadcn
dotnet add package Feliz.Shadcn
5. That's it
You can now start adding components to your project.
npx shadcn@2.3.0 add button
The command above will add the Button component to your project. You can then use it in your pages like this:
module FelizShadcnIntro.Pages.Page
open Feliz
open ElmishLand
open FelizShadcnIntro.Shared
open FelizShadcnIntro.Pages
open Feliz.Shadcn
type Model = {
Count: int
}
type Msg =
| LayoutMsg of Layout.Msg
| Increment
let init () =
{
Count = 0
},
Command.none
let update (msg: Msg) (model: Model) =
match msg with
| LayoutMsg _ -> model, Command.none
| Increment -> { model with Count = model.Count + 1}, Command.none
let view (_model: Model) (_dispatch: Msg -> unit) =
Html.div [
Html.div $"Count: {_model.Count}"
Shadcn.button [
prop.text "Increment"
prop.onClick (fun _ -> _dispatch Increment)
]
]
let page (_shared: SharedModel) (_route: HomeRoute) =
Page.from init update view () LayoutMsg
Run:
dotnet elmish-land server
to start your application.
Increment the counter by clicking a few times on the button. Change the button text to e.g. Increment (+1)
and save the file. Button's text should update, Count
should not reset to 0 (HMR works properly).