Style example with tailwind

This commit is contained in:
Paul-Henri Froidmont 2025-09-11 19:45:46 +02:00
parent 5dbf3d3ab6
commit 44ffa55cc6
Signed by: phfroidmont
GPG key ID: BE948AFD7E7873BE
5 changed files with 85 additions and 27 deletions

View file

@ -49,10 +49,32 @@ object example extends ScalaCommon:
PathRef(Task.dest) PathRef(Task.dest)
} }
def tailwindConfig = Task.Source(moduleDir / "tailwind.css")
def generateCss = Task {
sources()
os.proc(
"tailwindcss",
"--minify",
"--input",
tailwindConfig().path
).call().out.text()
}
def cssResources = Task {
os.write(
target = Task.dest / "public" / "app.css",
data = generateCss(),
createFolders = true
)
PathRef(Task.dest)
}
def resources = Task { def resources = Task {
super.resources() ++ Seq(scaliveBundle()) super.resources() :+ scaliveBundle() :+ cssResources()
} }
object js extends TypeScriptModule: object js extends TypeScriptModule:
def mainFileName = "app.js" def mainFileName = "app.js"
def npmDeps = Seq("phoenix@1.7.21", "phoenix_live_view@1.1.8", "topbar@3.0.0") def npmDeps = Seq("phoenix@1.7.21", "phoenix_live_view@1.1.8", "topbar@3.0.0")
end example

View file

@ -31,38 +31,66 @@ class ExampleLiveView(someParam: String) extends LiveView[Msg, Model]:
def view(model: Dyn[Model]) = def view(model: Dyn[Model]) =
div( div(
h1(someParam), h1(
h2(model(_.cls)), cls := "text-2xl font-semibold tracking-tight text-gray-900",
someParam
),
cls := "max-w-2xl mx-auto bg-white shadow rounded-2xl p-6 space-y-6",
idAttr := "42", idAttr := "42",
cls := model(_.cls),
ul( ul(
cls := "divide-y divide-gray-200",
model(_.elems).splitByIndex((_, elem) => model(_.elems).splitByIndex((_, elem) =>
li( li(
cls := "py-3 flex flex-wrap items-center justify-between gap-2",
span(
cls := "text-gray-700",
"Nom: ", "Nom: ",
elem(_.name), span(cls := "font-medium", elem(_.name))
" Age: ", ),
elem(_.age.toString) span(
cls := "text-sm text-gray-500",
"Age: ",
span(cls := "font-semibold text-gray-700", elem(_.age.toString))
)
) )
) )
), ),
div(
cls := "flex flex-wrap items-center gap-3",
button( button(
cls := "inline-flex items-center rounded-lg px-3 py-2 text-sm font-medium bg-gray-900 text-white shadow hover:opacity-90 focus:outline-none focus:ring-2 focus:ring-gray-900/30",
phx.click := Msg.IncAge(1), phx.click := Msg.IncAge(1),
"Inc age" "Inc age"
), ),
br(), span(cls := "grow"),
br(),
br(),
button( button(
cls := "inline-flex items-center rounded-lg px-3 py-2 text-sm font-medium ring-1 ring-inset ring-gray-300 text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-gray-400/30",
phx.click := Msg.ToggleCounter, phx.click := Msg.ToggleCounter,
model(_.isVisible match model(_.isVisible match
case true => "Hide counter" case true => "Hide counter"
case false => "Show counter") case false => "Show counter")
)
), ),
model.when(_.isVisible)( model.when(_.isVisible)(
div( div(
button(phx.click := Msg.DecCounter, "-"), cls := "rounded-xl border border-gray-200 p-4 bg-gray-50",
div(model(_.counter.toString)), div(
button(phx.click := Msg.IncCounter, "+") cls := "flex items-center justify-center gap-4",
button(
cls := "inline-flex items-center justify-center h-9 w-9 rounded-lg ring-1 ring-inset ring-gray-300 text-gray-700 hover:bg-white focus:outline-none focus:ring-2 focus:ring-gray-400/30",
phx.click := Msg.DecCounter,
"-"
),
div(
cls := "min-w-[4rem] text-center text-lg font-semibold text-gray-900",
model(_.counter.toString)
),
button(
cls := "inline-flex items-center justify-center h-9 w-9 rounded-lg bg-gray-900 text-white shadow hover:opacity-90 focus:outline-none focus:ring-2 focus:ring-gray-900/30",
phx.click := Msg.IncCounter,
"+"
)
)
) )
) )
) )
@ -83,6 +111,5 @@ object ExampleLiveView:
final case class Model( final case class Model(
isVisible: Boolean, isVisible: Boolean,
counter: Int, counter: Int,
elems: List[NestedModel], elems: List[NestedModel])
cls: String = "text-xs")
final case class NestedModel(name: String, age: Int) final case class NestedModel(name: String, age: Int)

View file

@ -8,6 +8,7 @@ object RootLayout:
metaTag(charset := "utf-8"), metaTag(charset := "utf-8"),
metaTag(nameAttr := "viewport", contentAttr := "width=device-width, initial-scale=1"), metaTag(nameAttr := "viewport", contentAttr := "width=device-width, initial-scale=1"),
scriptTag(defer := true, typ := "text/javascript", src := "/static/app.js"), scriptTag(defer := true, typ := "text/javascript", src := "/static/app.js"),
linkTag(rel := "stylesheet", href := "/static/app.css"),
titleTag("Scalive Example") titleTag("Scalive Example")
), ),
bodyTag( bodyTag(

7
example/tailwind.css Normal file
View file

@ -0,0 +1,7 @@
@import 'tailwindcss';
@plugin '@tailwindcss/forms';
@plugin '@tailwindcss/typography';
@plugin '@tailwindcss/aspect-ratio';
@source './src/**/*.scala';

View file

@ -11,10 +11,10 @@
let let
pkgs = nixpkgs.legacyPackages.${system}; pkgs = nixpkgs.legacyPackages.${system};
mill = pkgs.mill.overrideAttrs (old: rec { mill = pkgs.mill.overrideAttrs (old: rec {
version = "1.0.3"; version = "1.0.4";
src = pkgs.fetchurl { src = pkgs.fetchurl {
url = "https://repo1.maven.org/maven2/com/lihaoyi/mill-dist-native-linux-amd64/${version}/mill-dist-native-linux-amd64-${version}.exe"; url = "https://repo1.maven.org/maven2/com/lihaoyi/mill-dist-native-linux-amd64/${version}/mill-dist-native-linux-amd64-${version}.exe";
hash = "sha256-Q7Yc9MXnMmggyMeNq0nEoL1iNTGEbJpdwH2j8/JkJyI="; hash = "sha256-rgAqlTCZc8nedUU2D+Klo3KY0z9sI0KJczdaugM3//8=";
}; };
buildInputs = [ pkgs.zlib ]; buildInputs = [ pkgs.zlib ];
nativeBuildInputs = [ nativeBuildInputs = [
@ -41,6 +41,7 @@
buildInputs = [ buildInputs = [
mill mill
pkgs.scalafmt pkgs.scalafmt
pkgs.tailwindcss_4
]; ];
shellHook = "mill --bsp-install"; shellHook = "mill --bsp-install";
}; };