diff --git a/internal/server/routes.go b/internal/server/routes.go
index cf9dc51..f505ac6 100644
--- a/internal/server/routes.go
+++ b/internal/server/routes.go
@@ -10,6 +10,7 @@ import (
clicktoload "github.com/gofs-cli/template/internal/ui/pages/click-to-load"
deleterow "github.com/gofs-cli/template/internal/ui/pages/delete-row"
"github.com/gofs-cli/template/internal/ui/pages/home"
+ inlinevalidation "github.com/gofs-cli/template/internal/ui/pages/inline-validation"
"github.com/gofs-cli/template/internal/ui/pages/notfound"
"github.com/gofs-cli/template/internal/ui/pages/page1"
"github.com/gofs-cli/template/internal/ui/pages/page2"
@@ -45,6 +46,11 @@ func (s *Server) Routes() {
routesMux.Handle("GET /delete-row", deleterow.Index())
routesMux.Handle("DELETE /delete-row/contact/1", deleterow.Delete())
+ // inline validation example
+ routesMux.Handle("GET /inline-validation", inlinevalidation.Index())
+ routesMux.Handle("POST /inline-validation", inlinevalidation.Submit())
+ routesMux.Handle("POST /inline-validation/email", inlinevalidation.Validate())
+
routesMux.Handle("GET /modal", home.Modal())
routesMux.Handle("GET /page1", page1.Index())
diff --git a/internal/ui/pages/inline-validation/handlers.go b/internal/ui/pages/inline-validation/handlers.go
new file mode 100644
index 0000000..adaac41
--- /dev/null
+++ b/internal/ui/pages/inline-validation/handlers.go
@@ -0,0 +1,29 @@
+package inlinevalidation
+
+import (
+ "net/http"
+
+ "github.com/a-h/templ"
+ "github.com/gofs-cli/template/internal/ui"
+ "github.com/gofs-cli/template/internal/ui/components/header"
+)
+
+func Index() http.Handler {
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ templ.Handler(ui.IndexPage(layout(header.Header(), body()))).ServeHTTP(w, r)
+ })
+}
+
+func Submit() http.Handler {
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ e := r.PostFormValue("email")
+ templ.Handler(form(e)).ServeHTTP(w, r)
+ })
+}
+
+func Validate() http.Handler {
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ e := r.PostFormValue("email")
+ templ.Handler(email(e, e != "test@test.com")).ServeHTTP(w, r)
+ })
+}
diff --git a/internal/ui/pages/inline-validation/index.templ b/internal/ui/pages/inline-validation/index.templ
new file mode 100644
index 0000000..26e2e68
--- /dev/null
+++ b/internal/ui/pages/inline-validation/index.templ
@@ -0,0 +1,81 @@
+package inlinevalidation
+
+import "github.com/gofs-cli/template/internal/ui/components/toast"
+
+css classLayout() {
+ display: grid;
+}
+
+css formStyles() {
+ display: flex;
+ flex-direction: column;
+ gap: 8px;
+}
+
+css validInput() {
+ box-shadow: 0 0 3px #36cc00;
+}
+
+css errorInput() {
+ box-shadow: 0 0 3px #CC0000;
+}
+
+css errorMessage() {
+ color: red;
+}
+
+templ layout(header, body templ.Component) {
+ @toast.Container()
+
+
+ @header
+
+
+ @body
+
+
+}
+
+templ body() {
+
Inline Validation:
+ Enter an email into the input below and on tab out it will be validated. Only "test@test.com" will pass.
+ @form("")
+}
+
+templ form(emailAddress string) {
+
+}
+
+templ email(email string, err bool) {
+
+
+
+

+ if err {
+
That email is already taken. Please enter another email.
+ }
+
+}
diff --git a/internal/ui/pages/inline-validation/index_templ.go b/internal/ui/pages/inline-validation/index_templ.go
new file mode 100644
index 0000000..a565cc3
--- /dev/null
+++ b/internal/ui/pages/inline-validation/index_templ.go
@@ -0,0 +1,350 @@
+// Code generated by templ - DO NOT EDIT.
+
+// templ: version: v0.3.819
+package inlinevalidation
+
+//lint:file-ignore SA4006 This context is only used if a nested component is present.
+
+import "github.com/a-h/templ"
+import templruntime "github.com/a-h/templ/runtime"
+
+import "github.com/gofs-cli/template/internal/ui/components/toast"
+
+func classLayout() templ.CSSClass {
+ templ_7745c5c3_CSSBuilder := templruntime.GetBuilder()
+ templ_7745c5c3_CSSBuilder.WriteString(`display:grid;`)
+ templ_7745c5c3_CSSID := templ.CSSID(`classLayout`, templ_7745c5c3_CSSBuilder.String())
+ return templ.ComponentCSSClass{
+ ID: templ_7745c5c3_CSSID,
+ Class: templ.SafeCSS(`.` + templ_7745c5c3_CSSID + `{` + templ_7745c5c3_CSSBuilder.String() + `}`),
+ }
+}
+
+func formStyles() templ.CSSClass {
+ templ_7745c5c3_CSSBuilder := templruntime.GetBuilder()
+ templ_7745c5c3_CSSBuilder.WriteString(`display:flex;`)
+ templ_7745c5c3_CSSBuilder.WriteString(`flex-direction:column;`)
+ templ_7745c5c3_CSSBuilder.WriteString(`gap:8px;`)
+ templ_7745c5c3_CSSID := templ.CSSID(`formStyles`, templ_7745c5c3_CSSBuilder.String())
+ return templ.ComponentCSSClass{
+ ID: templ_7745c5c3_CSSID,
+ Class: templ.SafeCSS(`.` + templ_7745c5c3_CSSID + `{` + templ_7745c5c3_CSSBuilder.String() + `}`),
+ }
+}
+
+func validInput() templ.CSSClass {
+ templ_7745c5c3_CSSBuilder := templruntime.GetBuilder()
+ templ_7745c5c3_CSSBuilder.WriteString(`box-shadow:0 0 3px #36cc00;`)
+ templ_7745c5c3_CSSID := templ.CSSID(`validInput`, templ_7745c5c3_CSSBuilder.String())
+ return templ.ComponentCSSClass{
+ ID: templ_7745c5c3_CSSID,
+ Class: templ.SafeCSS(`.` + templ_7745c5c3_CSSID + `{` + templ_7745c5c3_CSSBuilder.String() + `}`),
+ }
+}
+
+func errorInput() templ.CSSClass {
+ templ_7745c5c3_CSSBuilder := templruntime.GetBuilder()
+ templ_7745c5c3_CSSBuilder.WriteString(`box-shadow:0 0 3px #CC0000;`)
+ templ_7745c5c3_CSSID := templ.CSSID(`errorInput`, templ_7745c5c3_CSSBuilder.String())
+ return templ.ComponentCSSClass{
+ ID: templ_7745c5c3_CSSID,
+ Class: templ.SafeCSS(`.` + templ_7745c5c3_CSSID + `{` + templ_7745c5c3_CSSBuilder.String() + `}`),
+ }
+}
+
+func errorMessage() templ.CSSClass {
+ templ_7745c5c3_CSSBuilder := templruntime.GetBuilder()
+ templ_7745c5c3_CSSBuilder.WriteString(`color:red;`)
+ templ_7745c5c3_CSSID := templ.CSSID(`errorMessage`, templ_7745c5c3_CSSBuilder.String())
+ return templ.ComponentCSSClass{
+ ID: templ_7745c5c3_CSSID,
+ Class: templ.SafeCSS(`.` + templ_7745c5c3_CSSID + `{` + templ_7745c5c3_CSSBuilder.String() + `}`),
+ }
+}
+
+func layout(header, body templ.Component) templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var1 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var1 == nil {
+ templ_7745c5c3_Var1 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ templ_7745c5c3_Err = toast.Container().Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var2 = []any{classLayout()}
+ templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var2...)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = header.Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = body.Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return nil
+ })
+}
+
+func body() templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var4 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var4 == nil {
+ templ_7745c5c3_Var4 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "Inline Validation:
Enter an email into the input below and on tab out it will be validated. Only \"test@test.com\" will pass.
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = form("").Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return nil
+ })
+}
+
+func form(emailAddress string) templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var5 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var5 == nil {
+ templ_7745c5c3_Var5 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ var templ_7745c5c3_Var6 = []any{formStyles()}
+ templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var6...)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return nil
+ })
+}
+
+func email(email string, err bool) templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var8 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var8 == nil {
+ templ_7745c5c3_Var8 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, " ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var9 = []any{errorInput()}
+ templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var9...)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var10 = []any{validInput()}
+ templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var10...)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "

")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ if err {
+ var templ_7745c5c3_Var14 = []any{errorMessage()}
+ templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var14...)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "
That email is already taken. Please enter another email.
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return nil
+ })
+}
+
+var _ = templruntime.GeneratedTemplate