1
0
gomponents/examples/tailwindcss/tailwindcss.go
Markus Wüstenberg f387a71230
Add generic Map implementation (#108)
Instead of waiting for a good time to switch the `Map` implementation,
I've decided to just offer two implementations: one for Go versions
before 1.18, and one for 1.18 and onwards. This is achieved using build
tags in the source files.

This is obviously a breaking change for consumers of this library that
use Go 1.18 and onwards.

See #88
2022-09-22 09:41:06 +02:00

129 lines
3.4 KiB
Go

//go:build go1.18
// +build go1.18
package main
import (
"net/http"
"time"
g "github.com/maragudk/gomponents"
c "github.com/maragudk/gomponents/components"
. "github.com/maragudk/gomponents/html"
)
func main() {
http.Handle("/", createHandler(indexPage()))
http.Handle("/contact", createHandler(contactPage()))
http.Handle("/about", createHandler(aboutPage()))
_ = http.ListenAndServe("localhost:8080", nil)
}
func createHandler(title string, body g.Node) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
// Rendering a Node is as simple as calling Render and passing an io.Writer
_ = Page(title, r.URL.Path, body).Render(w)
}
}
func indexPage() (string, g.Node) {
return "Welcome!", Div(
H1(g.Text("Welcome to this example page")),
P(g.Text("I hope it will make you happy. 😄 It's using TailwindCSS for styling.")),
)
}
func contactPage() (string, g.Node) {
return "Contact", Div(
H1(g.Text("Contact us")),
P(g.Text("Just do it.")),
)
}
func aboutPage() (string, g.Node) {
return "About", Div(
H1(g.Text("About this site")),
P(g.Text("This is a site showing off gomponents.")),
)
}
func Page(title, path string, body g.Node) g.Node {
// HTML5 boilerplate document
return c.HTML5(c.HTML5Props{
Title: title,
Language: "en",
Head: []g.Node{
Link(Rel("stylesheet"), Href("https://unpkg.com/tailwindcss@2.1.2/dist/base.min.css")),
Link(Rel("stylesheet"), Href("https://unpkg.com/tailwindcss@2.1.2/dist/components.min.css")),
Link(Rel("stylesheet"), Href("https://unpkg.com/@tailwindcss/typography@0.4.0/dist/typography.min.css")),
Link(Rel("stylesheet"), Href("https://unpkg.com/tailwindcss@2.1.2/dist/utilities.min.css")),
},
Body: []g.Node{
Navbar(path, []PageLink{
{Path: "/contact", Name: "Contact"},
{Path: "/about", Name: "About"},
}),
Container(
Prose(body),
PageFooter(),
),
},
})
}
type PageLink struct {
Path string
Name string
}
func Navbar(currentPath string, links []PageLink) g.Node {
return Nav(Class("bg-gray-700 mb-4"),
Container(
Div(Class("flex items-center space-x-4 h-16"),
NavbarLink("/", "Home", currentPath == "/"),
// We can Map custom slices to Nodes
g.Group(g.Map(links, func(pl PageLink) g.Node {
return NavbarLink(pl.Path, pl.Name, currentPath == pl.Path)
})),
),
),
)
}
// NavbarLink is a link in the Navbar.
func NavbarLink(path, text string, active bool) g.Node {
return A(Href(path), g.Text(text),
// Apply CSS classes conditionally
c.Classes{
"px-3 py-2 rounded-md text-sm font-medium focus:outline-none focus:text-white focus:bg-gray-700": true,
"text-white bg-gray-900": active,
"text-gray-300 hover:text-white hover:bg-gray-700": !active,
},
)
}
func Container(children ...g.Node) g.Node {
return Div(Class("max-w-7xl mx-auto px-2 sm:px-6 lg:px-8"), g.Group(children))
}
func Prose(children ...g.Node) g.Node {
return Div(Class("prose"), g.Group(children))
}
func PageFooter() g.Node {
return Footer(Class("prose prose-sm prose-indigo"),
P(
// We can use string interpolation directly, like fmt.Sprintf.
g.Textf("Rendered %v. ", time.Now().Format(time.RFC3339)),
// Conditional inclusion
g.If(time.Now().Second()%2 == 0, g.Text("It's an even second.")),
g.If(time.Now().Second()%2 == 1, g.Text("It's an odd second.")),
),
P(A(Href("https://www.gomponents.com"), g.Text("gomponents"))),
)
}