Use gotailwind (standalone Tailwind v4 via Go tool) with DaisyUI plugin files — no npm needed. CSS is compiled at build time and embedded via a Via Plugin that serves it as a static file. Custom "connect4" theme: light, warm, playful palette with red/yellow accents matching game pieces and board blue accent.
131 lines
3.5 KiB
Go
131 lines
3.5 KiB
Go
package ui
|
|
|
|
import (
|
|
"github.com/ryanhamamura/via/h"
|
|
)
|
|
|
|
func LoginView(usernameBind, passwordBind, loginKeyDown, loginClick h.H, errorMsg string) h.H {
|
|
var errorEl h.H
|
|
if errorMsg != "" {
|
|
errorEl = h.P(h.Class("alert alert-error mb-4"), h.Text(errorMsg))
|
|
}
|
|
|
|
return h.Main(h.Class("max-w-sm mx-auto mt-8 text-center"),
|
|
h.H1(h.Class("text-3xl font-bold"), h.Text("Login")),
|
|
h.P(h.Class("mb-4"), h.Text("Sign in to your account")),
|
|
errorEl,
|
|
h.Form(
|
|
h.FieldSet(h.Class("fieldset"),
|
|
h.Label(h.Class("label"), h.Text("Username"), h.Attr("for", "username")),
|
|
h.Input(
|
|
h.Class("input input-bordered w-full"),
|
|
h.ID("username"),
|
|
h.Type("text"),
|
|
h.Placeholder("Enter your username"),
|
|
usernameBind,
|
|
h.Attr("required"),
|
|
h.Attr("autofocus"),
|
|
),
|
|
h.Label(h.Class("label"), h.Text("Password"), h.Attr("for", "password")),
|
|
h.Input(
|
|
h.Class("input input-bordered w-full"),
|
|
h.ID("password"),
|
|
h.Type("password"),
|
|
h.Placeholder("Enter your password"),
|
|
passwordBind,
|
|
h.Attr("required"),
|
|
loginKeyDown,
|
|
),
|
|
),
|
|
h.Button(
|
|
h.Class("btn btn-primary w-full"),
|
|
h.Type("button"),
|
|
h.Text("Login"),
|
|
loginClick,
|
|
),
|
|
),
|
|
h.P(
|
|
h.Text("Don't have an account? "),
|
|
h.A(h.Class("link"), h.Href("/register"), h.Text("Register")),
|
|
),
|
|
)
|
|
}
|
|
|
|
func RegisterView(usernameBind, passwordBind, confirmBind, registerKeyDown, registerClick h.H, errorMsg string) h.H {
|
|
var errorEl h.H
|
|
if errorMsg != "" {
|
|
errorEl = h.P(h.Class("alert alert-error mb-4"), h.Text(errorMsg))
|
|
}
|
|
|
|
return h.Main(h.Class("max-w-sm mx-auto mt-8 text-center"),
|
|
h.H1(h.Class("text-3xl font-bold"), h.Text("Register")),
|
|
h.P(h.Class("mb-4"), h.Text("Create a new account")),
|
|
errorEl,
|
|
h.Form(
|
|
h.FieldSet(h.Class("fieldset"),
|
|
h.Label(h.Class("label"), h.Text("Username"), h.Attr("for", "username")),
|
|
h.Input(
|
|
h.Class("input input-bordered w-full"),
|
|
h.ID("username"),
|
|
h.Type("text"),
|
|
h.Placeholder("Choose a username"),
|
|
usernameBind,
|
|
h.Attr("required"),
|
|
h.Attr("autofocus"),
|
|
),
|
|
h.Label(h.Class("label"), h.Text("Password"), h.Attr("for", "password")),
|
|
h.Input(
|
|
h.Class("input input-bordered w-full"),
|
|
h.ID("password"),
|
|
h.Type("password"),
|
|
h.Placeholder("Choose a password (min 8 chars)"),
|
|
passwordBind,
|
|
h.Attr("required"),
|
|
),
|
|
h.Label(h.Class("label"), h.Text("Confirm Password"), h.Attr("for", "confirm")),
|
|
h.Input(
|
|
h.Class("input input-bordered w-full"),
|
|
h.ID("confirm"),
|
|
h.Type("password"),
|
|
h.Placeholder("Confirm your password"),
|
|
confirmBind,
|
|
h.Attr("required"),
|
|
registerKeyDown,
|
|
),
|
|
),
|
|
h.Button(
|
|
h.Class("btn btn-primary w-full"),
|
|
h.Type("button"),
|
|
h.Text("Register"),
|
|
registerClick,
|
|
),
|
|
),
|
|
h.P(
|
|
h.Text("Already have an account? "),
|
|
h.A(h.Class("link"), h.Href("/login"), h.Text("Login")),
|
|
),
|
|
)
|
|
}
|
|
|
|
func AuthHeader(username string, logoutClick h.H) h.H {
|
|
return h.Div(h.Class("flex justify-center items-center gap-4 mb-4 p-2 bg-base-200 rounded-lg"),
|
|
h.Span(h.Text("Logged in as "), h.Strong(h.Text(username))),
|
|
h.Button(
|
|
h.Type("button"),
|
|
h.Class("btn btn-ghost btn-sm"),
|
|
h.Text("Logout"),
|
|
logoutClick,
|
|
),
|
|
)
|
|
}
|
|
|
|
func GuestBanner() h.H {
|
|
return h.Div(h.Class("alert text-sm mb-4"),
|
|
h.Text("Playing as guest. "),
|
|
h.A(h.Class("link"), h.Href("/login"), h.Text("Login")),
|
|
h.Text(" or "),
|
|
h.A(h.Class("link"), h.Href("/register"), h.Text("Register")),
|
|
h.Text(" to save your games."),
|
|
)
|
|
}
|