From 370b3378f21997132b7d366fa361c6d18abef90a Mon Sep 17 00:00:00 2001 From: axzilla Date: Sat, 26 Oct 2024 09:28:45 +0200 Subject: [PATCH 01/17] SOFT WIP --- assets/css/output.css | 109 ++++++ cmd/server/main.go | 2 + internals/shared/menudata.go | 9 + internals/ui/pages/form.templ | 39 +++ internals/ui/pages/select.templ | 41 +++ internals/ui/pages/themes.templ | 2 +- internals/ui/showcase/form.templ | 166 +++++++++ internals/ui/showcase/radio_group.templ | 37 +- internals/ui/showcase/select.templ | 83 +++++ pkg/components/checkbox.templ | 29 +- pkg/components/checkbox_templ.go | 130 ++++++-- pkg/components/form.templ | 89 +++++ pkg/components/form_templ.go | 184 ++++++++++ pkg/components/input.templ | 1 - pkg/components/input_templ.go | 51 ++- pkg/components/radio_group.templ | 117 +++---- pkg/components/radio_group_templ.go | 155 ++++----- pkg/components/select.templ | 198 +++++++++++ pkg/components/select_templ.go | 426 ++++++++++++++++++++++++ pkg/styles/goilerplate.css | 127 +++++++ 20 files changed, 1755 insertions(+), 240 deletions(-) create mode 100644 internals/ui/pages/form.templ create mode 100644 internals/ui/pages/select.templ create mode 100644 internals/ui/showcase/form.templ create mode 100644 internals/ui/showcase/select.templ create mode 100644 pkg/components/form.templ create mode 100644 pkg/components/form_templ.go create mode 100644 pkg/components/select.templ create mode 100644 pkg/components/select_templ.go diff --git a/assets/css/output.css b/assets/css/output.css index 729005d..40e41fc 100644 --- a/assets/css/output.css +++ b/assets/css/output.css @@ -628,6 +628,10 @@ body { } } +.pointer-events-none { + pointer-events: none; +} + .static { position: static; } @@ -674,6 +678,10 @@ body { left: 0px; } +.left-2 { + left: 0.5rem; +} + .left-full { left: 100%; } @@ -759,6 +767,10 @@ body { margin-left: 0.25rem; } +.ml-2 { + margin-left: 0.5rem; +} + .ml-auto { margin-left: auto; } @@ -843,6 +855,10 @@ body { height: 6rem; } +.h-3\.5 { + height: 0.875rem; +} + .h-4 { height: 1rem; } @@ -887,6 +903,14 @@ body { max-height: 24rem; } +.max-h-\[15rem\] { + max-height: 15rem; +} + +.max-h-\[50vh\] { + max-height: 50vh; +} + .min-h-screen { min-height: 100vh; } @@ -911,6 +935,10 @@ body { width: 6rem; } +.w-3\.5 { + width: 0.875rem; +} + .w-3\/4 { width: 75%; } @@ -1202,6 +1230,12 @@ body { margin-bottom: calc(1.5rem * var(--tw-space-y-reverse)); } +.space-y-8 > :not([hidden]) ~ :not([hidden]) { + --tw-space-y-reverse: 0; + margin-top: calc(2rem * calc(1 - var(--tw-space-y-reverse))); + margin-bottom: calc(2rem * var(--tw-space-y-reverse)); +} + .divide-y > :not([hidden]) ~ :not([hidden]) { --tw-divide-y-reverse: 0; border-top-width: calc(1px * calc(1 - var(--tw-divide-y-reverse))); @@ -1213,6 +1247,10 @@ body { border-color: hsl(var(--border) / var(--tw-divide-opacity)); } +.overflow-auto { + overflow: auto; +} + .\!overflow-hidden { overflow: hidden !important; } @@ -1233,6 +1271,12 @@ body { overflow-y: auto; } +.truncate { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + .whitespace-nowrap { white-space: nowrap; } @@ -1319,6 +1363,11 @@ body { background-color: var(--theme-primary); } +.bg-accent { + --tw-bg-opacity: 1; + background-color: hsl(var(--accent) / var(--tw-bg-opacity)); +} + .bg-background { --tw-bg-opacity: 1; background-color: hsl(var(--background) / var(--tw-bg-opacity)); @@ -1343,6 +1392,10 @@ body { background-color: hsl(var(--destructive) / var(--tw-bg-opacity)); } +.bg-destructive\/10 { + background-color: hsl(var(--destructive) / 0.1); +} + .bg-gray-700 { --tw-bg-opacity: 1; background-color: rgb(55 65 81 / var(--tw-bg-opacity)); @@ -1475,6 +1528,11 @@ body { padding-bottom: 0.25rem; } +.py-1\.5 { + padding-top: 0.375rem; + padding-bottom: 0.375rem; +} + .py-12 { padding-top: 3rem; padding-bottom: 3rem; @@ -1518,10 +1576,22 @@ body { padding-left: 1.5rem; } +.pl-8 { + padding-left: 2rem; +} + +.pr-2 { + padding-right: 0.5rem; +} + .pt-0 { padding-top: 0px; } +.pt-4 { + padding-top: 1rem; +} + .pt-5 { padding-top: 1.25rem; } @@ -1900,6 +1970,26 @@ body { background-color: hsl(var(--primary) / var(--tw-bg-opacity)); } +.checked\:outline-none:checked { + outline: 2px solid transparent; + outline-offset: 2px; +} + +.checked\:ring-2:checked { + --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color); + --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color); + box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000); +} + +.checked\:ring-ring:checked { + --tw-ring-opacity: 1; + --tw-ring-color: hsl(var(--ring) / var(--tw-ring-opacity)); +} + +.checked\:ring-offset-2:checked { + --tw-ring-offset-width: 2px; +} + .hover\:bg-accent:hover { --tw-bg-opacity: 1; background-color: hsl(var(--accent) / var(--tw-bg-opacity)); @@ -1973,6 +2063,16 @@ body { opacity: 0.8; } +.focus\:bg-accent:focus { + --tw-bg-opacity: 1; + background-color: hsl(var(--accent) / var(--tw-bg-opacity)); +} + +.focus\:text-accent-foreground:focus { + --tw-text-opacity: 1; + color: hsl(var(--accent-foreground) / var(--tw-text-opacity)); +} + .focus\:outline-none:focus { outline: 2px solid transparent; outline-offset: 2px; @@ -1993,6 +2093,15 @@ body { --tw-ring-color: rgb(99 102 241 / var(--tw-ring-opacity)); } +.focus\:ring-ring:focus { + --tw-ring-opacity: 1; + --tw-ring-color: hsl(var(--ring) / var(--tw-ring-opacity)); +} + +.focus\:ring-offset-2:focus { + --tw-ring-offset-width: 2px; +} + .focus-visible\:outline-none:focus-visible { outline: 2px solid transparent; outline-offset: 2px; diff --git a/cmd/server/main.go b/cmd/server/main.go index 333a09c..142e3bc 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -31,10 +31,12 @@ func main() { mux.Handle("GET /docs/components/checkbox", templ.Handler(pages.Checkbox())) mux.Handle("GET /docs/components/datepicker", templ.Handler(pages.Datepicker())) mux.Handle("GET /docs/components/dropdown-menu", templ.Handler(pages.DropdownMenu())) + mux.Handle("GET /docs/components/form", templ.Handler(pages.Form())) mux.Handle("GET /docs/components/icon", templ.Handler(pages.Icon())) mux.Handle("GET /docs/components/input", templ.Handler(pages.Input())) mux.Handle("GET /docs/components/modal", templ.Handler(pages.Modal())) mux.Handle("GET /docs/components/radio-group", templ.Handler(pages.RadioGroup())) + mux.Handle("GET /docs/components/select", templ.Handler(pages.Select())) mux.Handle("GET /docs/components/sheet", templ.Handler(pages.Sheet())) mux.Handle("GET /docs/components/tabs", templ.Handler(pages.Tabs())) mux.Handle("GET /docs/components/toggle", templ.Handler(pages.Toggle())) diff --git a/internals/shared/menudata.go b/internals/shared/menudata.go index 98926ba..b7474b2 100644 --- a/internals/shared/menudata.go +++ b/internals/shared/menudata.go @@ -65,6 +65,11 @@ var Sections = []Section{ Text: "Dropdown Menu", Href: "/docs/components/dropdown-menu", }, + { + Text: "Form", + Href: "/docs/components/form", + }, + { Text: "Icon", Href: "/docs/components/icon", @@ -81,6 +86,10 @@ var Sections = []Section{ Text: "Radio Group", Href: "/docs/components/radio-group", }, + { + Text: "Select", + Href: "/docs/components/select", + }, { Text: "Sheet", Href: "/docs/components/sheet", diff --git a/internals/ui/pages/form.templ b/internals/ui/pages/form.templ new file mode 100644 index 0000000..6e53246 --- /dev/null +++ b/internals/ui/pages/form.templ @@ -0,0 +1,39 @@ +package pages + +import ( + "github.com/axzilla/goilerplate/internals/ui/layouts" + "github.com/axzilla/goilerplate/internals/ui/showcase" + "github.com/axzilla/goilerplate/pkg/components" +) + +templ Form() { + @layouts.DocsLayout() { +
+
+

Form

+

Building forms with Go, Templ & Alpine.js.

+
+ @components.Tabs(components.TabsProps{ + Tabs: []components.Tab{ + { + ID: "preview", + Title: "Preview", + Content: showcase.FormShowcase(), + }, + { + ID: "code", + Title: "Code", + Content: CodeSnippetFromEmbedded("form.templ", "go", showcase.TemplFiles), + }, + { + ID: "component", + Title: "Component", + Content: CodeSnippetFromEmbedded("form.templ", "go", components.TemplFiles), + }, + }, + TabsContainerClass: "md:w-1/2", + ContentContainerClass: "w-full", + }) +
+ } +} diff --git a/internals/ui/pages/select.templ b/internals/ui/pages/select.templ new file mode 100644 index 0000000..979f6b5 --- /dev/null +++ b/internals/ui/pages/select.templ @@ -0,0 +1,41 @@ +package pages + +import ( + "github.com/axzilla/goilerplate/internals/ui/layouts" + "github.com/axzilla/goilerplate/internals/ui/showcase" + "github.com/axzilla/goilerplate/pkg/components" +) + +templ Select() { + @layouts.DocsLayout() { +
+
+

Select

+

+ A dropdown menu for selecting a single value from a list of options. +

+
+ @components.Tabs(components.TabsProps{ + Tabs: []components.Tab{ + { + ID: "preview", + Title: "Preview", + Content: showcase.SelectShowcase(), + }, + { + ID: "code", + Title: "Code", + Content: CodeSnippetFromEmbedded("select.templ", "go", showcase.TemplFiles), + }, + { + ID: "component", + Title: "Component", + Content: CodeSnippetFromEmbedded("select.templ", "go", components.TemplFiles), + }, + }, + TabsContainerClass: "md:w-1/2", + ContentContainerClass: "w-full", + }) +
+ } +} diff --git a/internals/ui/pages/themes.templ b/internals/ui/pages/themes.templ index e12308b..94217f0 100644 --- a/internals/ui/pages/themes.templ +++ b/internals/ui/pages/themes.templ @@ -103,7 +103,7 @@ templ ThemePreview() {
- @components.RadioGroup(components.RadioGroupProps{DefaultValue: "email", Name: "contact-method"}) { + @components.RadioGroup(components.RadioGroupProps{Value: "email", Name: "contact-method"}) {
@components.RadioGroupItem(components.RadioGroupItemProps{ Value: "email", diff --git a/internals/ui/showcase/form.templ b/internals/ui/showcase/form.templ new file mode 100644 index 0000000..bd848b3 --- /dev/null +++ b/internals/ui/showcase/form.templ @@ -0,0 +1,166 @@ +package showcase + +import ( + "encoding/json" + "github.com/axzilla/goilerplate/pkg/components" +) + +type SignupFormData struct { + Email string `json:"email"` + Role string `json:"role"` + NotificationTypes []string `json:"notificationTypes"` + Newsletter bool `json:"newsletter"` + Terms bool `json:"terms"` +} + +func (d SignupFormData) ToJSON() string { + json, _ := json.Marshal(d) + return string(json) +} + +templ FormShowcase() { + @components.Form(components.FormProps[SignupFormData]{ + ID: "signup-form", + Name: "signup", + Action: "/api/signup", + InitialData: SignupFormData{ + Email: "", + Role: "", + NotificationTypes: []string{}, + Newsletter: true, + Terms: true, + }, + Debug: true, + }) { +

Account Settings

+ // Email Input +
+ + @components.Input(components.InputProps{ + Type: "email", + Name: "email", + Placeholder: "Enter your email", + Attributes: templ.Attributes{"x-model": "formData.email"}, + }) +
+ // Role Select +
+ + @components.Select(components.SelectProps{ + ID: "role", + Name: "role", + Placeholder: "Select role", + Value: "formData.role", + Options: []components.SelectOption{ + {Label: "User", Value: "user"}, + {Label: "Admin", Value: "admin"}, + {Label: "Editor", Value: "editor", Disabled: "true"}, + }, + }) +
+ // Notification Types (Multiple Checkboxes) +
+ +
+ @components.Checkbox(components.CheckboxProps{ + ID: "notify-email", + Name: "notificationTypes", + Value: "email", + Label: "Email Notifications", + Attributes: templ.Attributes{ + ":checked": "formData.notificationTypes.includes('email')", + "@click": `() => { + const i = formData.notificationTypes.indexOf('email'); + const n = formData.notificationTypes; + i > -1 ? n.splice(i, 1) : n.push('email'); + }`, + }, + }) + @components.Checkbox(components.CheckboxProps{ + ID: "notify-sms", + Name: "notificationTypes", + Value: "sms", + Label: "SMS Notifications", + Attributes: templ.Attributes{ + ":checked": "formData.notificationTypes.includes('sms')", + "@click": `() => { + const index = formData.notificationTypes.indexOf('sms'); + if (index > -1) { + formData.notificationTypes.splice(index, 1); + } else { + formData.notificationTypes.push('sms'); + } + }`, + }, + }) +
+
+ // Marketing Consent (Radio) +
+ + @components.RadioGroup(components.RadioGroupProps{ + Name: "marketing", + Value: "formData.marketingConsent", + }) { +
+ @components.RadioGroupItem(components.RadioGroupItemProps{ + Value: "all", + ID: "marketing-all", + Label: templ.Raw("All marketing emails"), + Attributes: templ.Attributes{"x-model": "formData.marketingConsent"}, + }) + @components.RadioGroupItem(components.RadioGroupItemProps{ + Value: "selected", + ID: "marketing-selected", + Label: templ.Raw("Only selected emails"), + Attributes: templ.Attributes{"x-model": "formData.marketingConsent"}, + }) + @components.RadioGroupItem(components.RadioGroupItemProps{ + Value: "none", + ID: "marketing-none", + Label: templ.Raw("No marketing emails"), + Attributes: templ.Attributes{"x-model": "formData.marketingConsent"}, + }) +
+ } +
+ // Newsletter Toggle +
+ @components.Toggle(components.ToggleProps{ + ID: "newsletter", + Name: "newsletter", + LabelRight: "Subscribe to newsletter", + Checked: "formData.newsletter", + Attributes: templ.Attributes{ + "x-model": "formData.newsletter", + }, + }) + +
+
+ // Terms Checkbox +
+ @components.Checkbox(components.CheckboxProps{ + ID: "terms", + Name: "terms", + Label: "I accept the terms and conditions", + Checked: "formData.terms", + // Attributes: templ.Attributes{ + // "x-model": "formData.terms", + // }, + }) +
+ // Submit Button +
+ @components.Button(components.ButtonProps{ + Text: "Save Changes", + Attributes: templ.Attributes{ + "@click": "submit", + }, + }) +
+ } +} diff --git a/internals/ui/showcase/radio_group.templ b/internals/ui/showcase/radio_group.templ index 36dc735..a5dc669 100644 --- a/internals/ui/showcase/radio_group.templ +++ b/internals/ui/showcase/radio_group.templ @@ -1,32 +1,33 @@ package showcase -import ( - "github.com/axzilla/goilerplate/pkg/components" -) +import "github.com/axzilla/goilerplate/pkg/components" templ RadioGroupShowcase() {
-
- @components.RadioGroup(components.RadioGroupProps{DefaultValue: "comfortable", Name: "view-mode"}) { +
+ @components.RadioGroup(components.RadioGroupProps{Value: "'default'", Name: "view-mode"}) {
@components.RadioGroupItem(components.RadioGroupItemProps{ - Value: "default", - ID: "r1", - Name: "view-mode", - Label: templ.Raw("Default"), + Value: "default", + ID: "r1", + Name: "view-mode", + Label: templ.Raw("Default"), + Attributes: templ.Attributes{"x-model": "checked"}, }) @components.RadioGroupItem(components.RadioGroupItemProps{ - Value: "comfortable", - ID: "r2", - Name: "view-mode", - Disabled: "true", - Label: templ.Raw("Comfortable"), + Value: "comfortable", + ID: "r2", + Name: "view-mode", + Disabled: "true", + Label: templ.Raw("Comfortable"), + Attributes: templ.Attributes{"x-model": "checked"}, }) @components.RadioGroupItem(components.RadioGroupItemProps{ - Value: "compact", - ID: "r3", - Name: "view-mode", - Label: templ.Raw("Compact"), + Value: "compact", + ID: "r3", + Name: "view-mode", + Label: templ.Raw("Compact"), + Attributes: templ.Attributes{"x-model": "checked"}, })
} diff --git a/internals/ui/showcase/select.templ b/internals/ui/showcase/select.templ new file mode 100644 index 0000000..cf3ecde --- /dev/null +++ b/internals/ui/showcase/select.templ @@ -0,0 +1,83 @@ +package showcase + +import "github.com/axzilla/goilerplate/pkg/components" + +var xxx = "banana" + +templ SelectShowcase() { +
+
+
+

Default Select

+ @components.Select(components.SelectProps{ + ID: "fruit", + Name: "fruit", + Placeholder: "Select a fruit", + Options: []components.SelectOption{ + {Label: "Apple", Value: "apple"}, + {Label: "Banana", Value: "banana"}, + {Label: "Orange", Value: "orange"}, + {Label: "Mango", Value: "mango"}, + }, + }) +
+
+

Selected Value

+ @components.Select(components.SelectProps{ + ID: "selected", + Name: "selected", + Value: "banana", + Options: []components.SelectOption{ + {Label: "Apple", Value: "apple"}, + {Label: "Banana", Value: "banana"}, + {Label: "Orange", Value: "orange"}, + }, + }) +
+
+

Disabled Select

+ @components.Select(components.SelectProps{ + ID: "disabled", + Name: "disabled", + Placeholder: "Select is disabled", + Disabled: "true", + Options: []components.SelectOption{ + {Label: "Option 1", Value: "1"}, + {Label: "Option 2", Value: "2"}, + }, + }) +
+
+

With Disabled Options

+ @components.Select(components.SelectProps{ + ID: "disabled-options", + Name: "disabled-options", + Placeholder: "Select an option", + Options: []components.SelectOption{ + {Label: "Available", Value: "available"}, + {Label: "Out of Stock", Value: "out-of-stock", Disabled: "true"}, + {Label: "In Stock", Value: "in-stock"}, + {Label: "Discontinued", Value: "discontinued", Disabled: "true"}, + }, + }) +
+
+

Dynamic Example

+
+ @components.Select(components.SelectProps{ + ID: "user-type", + Name: "user-type", + Placeholder: "Select user type", + Value: "userType", + Options: []components.SelectOption{ + {Label: "Admin", Value: "admin"}, + {Label: "User", Value: "user"}, + {Label: "Guest", Value: "guest"}, + }, + }) +

+
+
+
+
+} diff --git a/pkg/components/checkbox.templ b/pkg/components/checkbox.templ index 4555b90..9833bd5 100644 --- a/pkg/components/checkbox.templ +++ b/pkg/components/checkbox.templ @@ -1,6 +1,9 @@ package components -import "github.com/axzilla/goilerplate/pkg/icons" +import ( + "fmt" + "github.com/axzilla/goilerplate/pkg/icons" +) // CheckboxProps defines the properties for the Checkbox component. type CheckboxProps struct { @@ -64,10 +67,10 @@ templ Checkbox(props CheckboxProps) { id={ props.ID } name={ props.Name } value={ props.Value } - x-ref="checkbox" - x-model="checked" if props.Checked != "" { - x-init={ "checked = " + props.Checked } + x-model={ props.Checked } + } else { + x-model="checked" } if props.Disabled != "" { :disabled={ props.Disabled } @@ -82,16 +85,26 @@ templ Checkbox(props CheckboxProps) { flex items-center justify-center bg-background peer-checked:bg-primary transition-colors" > -
- @icons.Check(icons.IconProps{Size: "12"}) -
+ if props.Checked != "" { +
+ @icons.Check(icons.IconProps{Size: "12"}) +
+ } else { +
+ @icons.Check(icons.IconProps{Size: "12"}) +
+ }
if props.Label != "" { diff --git a/pkg/components/checkbox_templ.go b/pkg/components/checkbox_templ.go index 1b719b1..41ed3d9 100644 --- a/pkg/components/checkbox_templ.go +++ b/pkg/components/checkbox_templ.go @@ -8,7 +8,10 @@ package components import "github.com/a-h/templ" import templruntime "github.com/a-h/templ/runtime" -import "github.com/axzilla/goilerplate/pkg/icons" +import ( + "fmt" + "github.com/axzilla/goilerplate/pkg/icons" +) // CheckboxProps defines the properties for the Checkbox component. type CheckboxProps struct { @@ -110,7 +113,7 @@ func Checkbox(props CheckboxProps) templ.Component { var templ_7745c5c3_Var4 string templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(props.ID) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/components/checkbox.templ`, Line: 64, Col: 17} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/components/checkbox.templ`, Line: 67, Col: 17} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) if templ_7745c5c3_Err != nil { @@ -123,7 +126,7 @@ func Checkbox(props CheckboxProps) templ.Component { var templ_7745c5c3_Var5 string templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(props.Name) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/components/checkbox.templ`, Line: 65, Col: 21} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/components/checkbox.templ`, Line: 68, Col: 21} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) if templ_7745c5c3_Err != nil { @@ -136,25 +139,25 @@ func Checkbox(props CheckboxProps) templ.Component { var templ_7745c5c3_Var6 string templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(props.Value) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/components/checkbox.templ`, Line: 66, Col: 23} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/components/checkbox.templ`, Line: 69, Col: 23} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" x-ref=\"checkbox\" x-model=\"checked\"") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if props.Checked != "" { - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" x-init=\"") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" x-model=\"") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var7 string - templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs("checked = " + props.Checked) + templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(props.Checked) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/components/checkbox.templ`, Line: 70, Col: 42} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/components/checkbox.templ`, Line: 71, Col: 28} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7)) if templ_7745c5c3_Err != nil { @@ -164,6 +167,11 @@ func Checkbox(props CheckboxProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } + } else { + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" x-model=\"checked\"") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } } if props.Disabled != "" { _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" :disabled=\"") @@ -173,7 +181,7 @@ func Checkbox(props CheckboxProps) templ.Component { var templ_7745c5c3_Var8 string templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(props.Disabled) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/components/checkbox.templ`, Line: 73, Col: 31} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/components/checkbox.templ`, Line: 76, Col: 31} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) if templ_7745c5c3_Err != nil { @@ -192,15 +200,51 @@ func Checkbox(props CheckboxProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(">
") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(">
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = icons.Check(icons.IconProps{Size: "12"}).Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err + if props.Checked != "" { + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = icons.Check(icons.IconProps{Size: "12"}).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } else { + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = icons.Check(icons.IconProps{Size: "12"}).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -209,28 +253,56 @@ func Checkbox(props CheckboxProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var9 string - templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(props.ID) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/components/checkbox.templ`, Line: 92, Col: 18} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" class=\"text-sm font-medium leading-none cursor-pointer select-none\" :class=\"{ 'text-muted-foreground': !checked, 'text-foreground': checked }\">") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } var templ_7745c5c3_Var10 string - templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(props.Label) + templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(props.ID) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/components/checkbox.templ`, Line: 96, Col: 17} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/components/checkbox.templ`, Line: 101, Col: 18} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" class=\"text-sm font-medium leading-none cursor-pointer select-none\"") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if props.Checked != "" { + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" :class=\"") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var11 string + templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("{ 'text-muted-foreground': !%s, 'text-foreground': %s }", props.Checked, props.Checked)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/components/checkbox.templ`, Line: 104, Col: 114} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } else { + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" :class=\"{ 'text-muted-foreground': !checked, 'text-foreground': checked }\"") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(">") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var12 string + templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(props.Label) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/components/checkbox.templ`, Line: 109, Col: 17} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err diff --git a/pkg/components/form.templ b/pkg/components/form.templ new file mode 100644 index 0000000..36aa593 --- /dev/null +++ b/pkg/components/form.templ @@ -0,0 +1,89 @@ +package components + +import "fmt" + +// Basis Interface für Form Daten +type FormDataProvider interface { + // Muss JSON-serialisierbar sein + ToJSON() string +} + +// FormProps definiert die Basis-Konfiguration der Form +type FormProps[T FormDataProvider] struct { + // Core configuration + ID string + Name string + Class string + + // Form handling + Action string + Method string + + // Initial form data + InitialData T + + // Debug mode + Debug bool + + // Additional attributes + Attributes templ.Attributes +} + +// Form Component +templ Form[T FormDataProvider](props FormProps[T]) { +
+
+ { children... } + if props.Debug { + @FormDebug() + } +
+} + +// Form Debug Component +templ FormDebug() { +
+
+

Form Debug

+ +
+
+
+

Form Data:

+

+			
+
+

Errors:

+

+			
+
+

State:

+
+
Submitting:
+
Submitted:
+
+
+
+
+} diff --git a/pkg/components/form_templ.go b/pkg/components/form_templ.go new file mode 100644 index 0000000..27df1c9 --- /dev/null +++ b/pkg/components/form_templ.go @@ -0,0 +1,184 @@ +// Code generated by templ - DO NOT EDIT. + +// templ: version: v0.2.778 +package components + +//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 "fmt" + +// Basis Interface für Form Daten +type FormDataProvider interface { + // Muss JSON-serialisierbar sein + ToJSON() string +} + +// FormProps definiert die Basis-Konfiguration der Form +type FormProps[T FormDataProvider] struct { + // Core configuration + ID string + Name string + Class string + + // Form handling + Action string + Method string + + // Initial form data + InitialData T + + // Debug mode + Debug bool + + // Additional attributes + Attributes templ.Attributes +} + +// Form Component +func Form[T FormDataProvider](props FormProps[T]) 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) + var templ_7745c5c3_Var2 = []any{"space-y-6", props.Class} + templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var2...) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ_7745c5c3_Var1.Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if props.Debug { + templ_7745c5c3_Err = FormDebug().Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) +} + +// Form Debug Component +func FormDebug() 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_Var7 := templ.GetChildren(ctx) + if templ_7745c5c3_Var7 == nil { + templ_7745c5c3_Var7 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("

Form Debug

Form Data:

Errors:

State:

Submitting:
Submitted:
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) +} + +var _ = templruntime.GeneratedTemplate diff --git a/pkg/components/input.templ b/pkg/components/input.templ index 2038a37..11b6bec 100644 --- a/pkg/components/input.templ +++ b/pkg/components/input.templ @@ -88,7 +88,6 @@ templ Input(props InputProps) { @@ -79,64 +74,38 @@ templ RadioGroup(props RadioGroupProps) { } // RadioGroupItem renders a single radio button with an integrated label. -// It uses Alpine.js for managing the disabled state and selected value. +// It uses Alpine.js for state management and accessibility features. // // Usage: // -// @components.RadioGroupItem(components.RadioGroupItemProps{ -// Value: "option1", -// Name: "myRadioGroup", -// ID: "option1", -// Disabled: "someCondition === true", // Alpine.js expression -// Label: templ.Raw("Option 1"), -// }) +// @components.RadioGroupItem(components.RadioGroupItemProps{ +// Value: "email", +// Name: "marketing", +// ID: "marketing-email", +// Disabled: "isLoading", +// Label: templ.Raw("Email Marketing"), +// }) templ RadioGroupItem(props RadioGroupItemProps) { -
@@ -149,7 +149,7 @@ templ ThemePreview() { ID: "beta", Name: "beta", LabelRight: "Join beta program", - Disabled: "true", + Attributes: templ.Attributes{"disabled": "true"}, })
diff --git a/internals/ui/showcase/toggle.templ b/internals/ui/showcase/toggle.templ index b64f1b6..316043c 100644 --- a/internals/ui/showcase/toggle.templ +++ b/internals/ui/showcase/toggle.templ @@ -29,25 +29,24 @@ templ ToggleShowcase() {

States

-
+
@components.Toggle(components.ToggleProps{ ID: "toggle-checked", Name: "toggle-checked", LabelRight: "Checked Toggle", - Checked: "1+1==2", + Attributes: templ.Attributes{"x-bind:checked": "true"}, }) @components.Toggle(components.ToggleProps{ ID: "toggle-disabled", Name: "toggle-disabled", LabelRight: "Disabled Toggle", - Disabled: "true", + Attributes: templ.Attributes{"disabled": "true"}, }) @components.Toggle(components.ToggleProps{ ID: "toggle-disabled-checked", Name: "toggle-disabled-checked", LabelRight: "Disabled Checked Toggle", - Disabled: "true", - Checked: "true", + Attributes: templ.Attributes{"checked": "true", "disabled": true}, })
diff --git a/pkg/components/toggle.templ b/pkg/components/toggle.templ index 0682afb..20348c4 100644 --- a/pkg/components/toggle.templ +++ b/pkg/components/toggle.templ @@ -20,16 +20,6 @@ type ToggleProps struct { // Label is the text label for the toggle LabelRight string - // It's treated as an Alpine.js expression for dynamic checking. - // Example bool: Checked: "true" - // Example string: Checked: "darkMode" - Checked string - - // It's treated as an Alpine.js expression for dynamic checking. - // Example bool: Disabled: "true" - // Example string: Disabled: "isLoading" - Disabled string - // Class specifies additional CSS classes Class string @@ -41,94 +31,36 @@ type ToggleProps struct { // It can be customized with different label placements, and supports // both static and dynamic states through Alpine.js integration. // -// Usage: -// -// // Basic toggle with label -// @components.Toggle(components.ToggleProps{ -// ID: "dark-mode", -// Name: "darkMode", -// LabelLeft: "Dark Mode", -// }) -// -// // Toggle with Alpine.js binding -// @components.Toggle(components.ToggleProps{ -// ID: "notifications", -// Name: "notifications", -// LabelLeft: "Enable Notifications", -// Checked: "notificationsEnabled", -// Disabled: "isLoading", -// }) -// -// // Toggle with custom size and label placement -// @components.Toggle(components.ToggleProps{ -// ID: "alerts", -// Name: "alerts", -// LabelLeft: "Alerts", -// }) -// // Props: // - ID: The unique identifier for the toggle input. Required. // - Name: The name attribute for the toggle input. Required. // - LabelLeft: The text label for the toggle. Optional. // - LabelRight: The text label for the toggle. Optional. -// - Checked: Controls the checked state. Can be bool or string for Alpine.js binding. Optional. -// - Disabled: Controls the disabled state. Can be bool or string for Alpine.js binding. Optional. // - Class: Additional CSS classes. Optional. // - Attributes: Additional HTML attributes. Optional. templ Toggle(props ToggleProps) { -
+
+ } diff --git a/pkg/components/toggle_templ.go b/pkg/components/toggle_templ.go index a5ce78b..d24c9cd 100644 --- a/pkg/components/toggle_templ.go +++ b/pkg/components/toggle_templ.go @@ -28,16 +28,6 @@ type ToggleProps struct { // Label is the text label for the toggle LabelRight string - // It's treated as an Alpine.js expression for dynamic checking. - // Example bool: Checked: "true" - // Example string: Checked: "darkMode" - Checked string - - // It's treated as an Alpine.js expression for dynamic checking. - // Example bool: Disabled: "true" - // Example string: Disabled: "isLoading" - Disabled string - // Class specifies additional CSS classes Class string @@ -49,38 +39,11 @@ type ToggleProps struct { // It can be customized with different label placements, and supports // both static and dynamic states through Alpine.js integration. // -// Usage: -// -// // Basic toggle with label -// @components.Toggle(components.ToggleProps{ -// ID: "dark-mode", -// Name: "darkMode", -// LabelLeft: "Dark Mode", -// }) -// -// // Toggle with Alpine.js binding -// @components.Toggle(components.ToggleProps{ -// ID: "notifications", -// Name: "notifications", -// LabelLeft: "Enable Notifications", -// Checked: "notificationsEnabled", -// Disabled: "isLoading", -// }) -// -// // Toggle with custom size and label placement -// @components.Toggle(components.ToggleProps{ -// ID: "alerts", -// Name: "alerts", -// LabelLeft: "Alerts", -// }) -// // Props: // - ID: The unique identifier for the toggle input. Required. // - Name: The name attribute for the toggle input. Required. // - LabelLeft: The text label for the toggle. Optional. // - LabelRight: The text label for the toggle. Optional. -// - Checked: Controls the checked state. Can be bool or string for Alpine.js binding. Optional. -// - Disabled: Controls the disabled state. Can be bool or string for Alpine.js binding. Optional. // - Class: Additional CSS classes. Optional. // - Attributes: Additional HTML attributes. Optional. func Toggle(props ToggleProps) templ.Component { @@ -104,155 +67,100 @@ func Toggle(props ToggleProps) templ.Component { templ_7745c5c3_Var1 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if props.LabelLeft != "" { + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var5 string - templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(props.Disabled) + templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(props.LabelLeft) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/components/toggle.templ`, Line: 89, Col: 30} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/components/toggle.templ`, Line: 53, Col: 21} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" x-model=\"checked\"> ") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - if props.LabelLeft != "" { - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - var templ_7745c5c3_Var7 = []any{ - "relative inline-flex h-6 py-0.5 focus:outline-none rounded-full w-10", - "disabled:opacity-50 disabled:cursor-not-allowed", - } - templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var7...) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - if props.LabelRight != "" { - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/pkg/styles/goilerplate.css b/pkg/styles/goilerplate.css index 5d77d58..f0cebe3 100644 --- a/pkg/styles/goilerplate.css +++ b/pkg/styles/goilerplate.css @@ -449,46 +449,47 @@ video { :root { --background: 0 0% 100%; --foreground: 240 10% 3.9%; - --card: 0 0% 100%; - --card-foreground: 240 10% 3.9%; - --popover: 0 0% 100%; - --popover-foreground: 240 10% 3.9%; - --primary: 240 5.9% 10%; - --primary-foreground: 0 0% 98%; - --secondary: 240 4.8% 95.9%; - --secondary-foreground: 240 5.9% 10%; --muted: 240 4.8% 95.9%; --muted-foreground: 240 3.8% 46.1%; - --accent: 240 4.8% 95.9%; - --accent-foreground: 240 5.9% 10%; - --destructive: 0 72.22% 50.59%; - --destructive-foreground: 0 0% 98%; + --popover: 0 0% 100%; + --popover-foreground: 240 10% 3.9%; + --card: 0 0% 100%; + --card-foreground: 240 10% 3.9%; --border: 240 5.9% 90%; --input: 240 5.9% 90%; - --ring: 240 5.9% 10%; + --primary: 346.8 77.2% 49.8%; + --primary-foreground: 355.7 100% 97.3%; + --secondary: 240 4.8% 95.9%; + --secondary-foreground: 240 5.9% 10%; + --accent: 240 4.8% 95.9%; + --accent-foreground: 240 5.9% 10%; + --destructive: 0 84.2% 60.2%; + --destructive-foreground: 0 0% 98%; + --ring: 346.8 77.2% 49.8%; --radius: 0.5rem; } .dark { - --background: 240 10% 3.9%; - --foreground: 0 0% 98%; - --card: 240 10% 3.9%; - --card-foreground: 0 0% 98%; - --popover: 240 10% 3.9%; - --popover-foreground: 0 0% 98%; - --primary: 0 0% 98%; - --primary-foreground: 240 5.9% 10%; - --secondary: 240 3.7% 15.9%; - --secondary-foreground: 0 0% 98%; - --muted: 240 3.7% 15.9%; + --background: 20 14.3% 4.1%; + --foreground: 0 0% 95%; + --muted: 0 0% 15%; --muted-foreground: 240 5% 64.9%; - --accent: 240 3.7% 15.9%; - --accent-foreground: 0 0% 98%; - --destructive: 0 62.8% 30.6%; - --destructive-foreground: 0 0% 98%; + --popover: 0 0% 9%; + --popover-foreground: 0 0% 95%; + --card: 24 9.8% 10%; + --card-foreground: 0 0% 95%; --border: 240 3.7% 15.9%; --input: 240 3.7% 15.9%; - --ring: 240 4.9% 83.9%; + --primary: 346.8 77.2% 49.8%; + --primary-foreground: 355.7 100% 97.3%; + --secondary: 240 3.7% 15.9%; + --secondary-foreground: 0 0% 98%; + --accent: 12 6.5% 15.1%; + --accent-foreground: 0 0% 98%; + --destructive: 0 62.8% 30.6%; + --destructive-foreground: 0 85.7% 97.3%; + --ring: 346.8 77.2% 49.8%; + --radius: 0.5rem; } * { @@ -628,6 +629,18 @@ body { } } +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border-width: 0; +} + .pointer-events-none { pointer-events: none; } @@ -891,10 +904,6 @@ body { width: 1rem; } -.w-5 { - width: 1.25rem; -} - .w-56 { width: 14rem; } @@ -946,16 +955,6 @@ body { transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); } -.translate-x-0\.5 { - --tw-translate-x: 0.125rem; - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); -} - -.translate-x-\[18px\] { - --tw-translate-x: 18px; - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); -} - .translate-x-full { --tw-translate-x: 100%; transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); @@ -1249,11 +1248,6 @@ body { background-color: hsl(var(--muted) / var(--tw-bg-opacity)); } -.bg-muted-foreground { - --tw-bg-opacity: 1; - background-color: hsl(var(--muted-foreground) / var(--tw-bg-opacity)); -} - .bg-muted\/50 { background-color: hsl(var(--muted) / 0.5); } @@ -1337,11 +1331,6 @@ body { padding-right: 2rem; } -.py-0\.5 { - padding-top: 0.125rem; - padding-bottom: 0.125rem; -} - .py-1 { padding-top: 0.25rem; padding-bottom: 0.25rem; @@ -1712,6 +1701,54 @@ body { color: hsl(var(--muted-foreground) / var(--tw-text-opacity)); } +.after\:absolute::after { + content: var(--tw-content); + position: absolute; +} + +.after\:left-0\.5::after { + content: var(--tw-content); + left: 0.125rem; +} + +.after\:top-0\.5::after { + content: var(--tw-content); + top: 0.125rem; +} + +.after\:h-5::after { + content: var(--tw-content); + height: 1.25rem; +} + +.after\:w-5::after { + content: var(--tw-content); + width: 1.25rem; +} + +.after\:rounded-full::after { + content: var(--tw-content); + border-radius: 9999px; +} + +.after\:bg-muted-foreground::after { + content: var(--tw-content); + --tw-bg-opacity: 1; + background-color: hsl(var(--muted-foreground) / var(--tw-bg-opacity)); +} + +.after\:transition-all::after { + content: var(--tw-content); + transition-property: all; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; +} + +.after\:content-\[\'\'\]::after { + --tw-content: ''; + content: var(--tw-content); +} + .checked\:border-primary:checked { --tw-border-opacity: 1; border-color: hsl(var(--primary) / var(--tw-border-opacity)); @@ -1895,6 +1932,23 @@ body { background-color: hsl(var(--primary) / var(--tw-bg-opacity)); } +.peer:checked ~ .peer-checked\:text-foreground { + --tw-text-opacity: 1; + color: hsl(var(--foreground) / var(--tw-text-opacity)); +} + +.peer:checked ~ .peer-checked\:after\:translate-x-\[16px\]::after { + content: var(--tw-content); + --tw-translate-x: 16px; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.peer:checked ~ .peer-checked\:after\:bg-secondary::after { + content: var(--tw-content); + --tw-bg-opacity: 1; + background-color: hsl(var(--secondary) / var(--tw-bg-opacity)); +} + .peer:focus-visible ~ .peer-focus-visible\:ring-2 { --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color); --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color); From fad8c8b099d404dfef9818e8b3d6f39fcf69f009 Mon Sep 17 00:00:00 2001 From: axzilla Date: Tue, 19 Nov 2024 14:24:07 +0700 Subject: [PATCH 03/17] change: simplify checkbox component --- assets/css/output.css | 104 ++++++++++-- internals/ui/showcase/checkbox.templ | 31 ++-- pkg/components/checkbox.templ | 95 ++++------- pkg/components/checkbox_templ.go | 228 ++++++--------------------- pkg/styles/goilerplate.css | 104 ++++++++++-- 5 files changed, 271 insertions(+), 291 deletions(-) diff --git a/assets/css/output.css b/assets/css/output.css index f205a69..0b680fd 100644 --- a/assets/css/output.css +++ b/assets/css/output.css @@ -645,6 +645,10 @@ body { pointer-events: none; } +.invisible { + visibility: hidden; +} + .static { position: static; } @@ -691,6 +695,10 @@ body { left: 0px; } +.left-1\/2 { + left: 50%; +} + .left-2 { left: 0.5rem; } @@ -715,6 +723,10 @@ body { top: 0px; } +.top-1\/2 { + top: 50%; +} + .top-2 { top: 0.5rem; } @@ -844,6 +856,16 @@ body { aspect-ratio: 1 / 1; } +.size-3 { + width: 0.75rem; + height: 0.75rem; +} + +.size-4 { + width: 1rem; + height: 1rem; +} + .h-1\/2 { height: 50%; } @@ -1033,6 +1055,11 @@ body { transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); } +.-translate-x-1\/2 { + --tw-translate-x: -50%; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + .-translate-x-1\/4 { --tw-translate-x: -25%; transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); @@ -1043,6 +1070,11 @@ body { transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); } +.-translate-y-1\/2 { + --tw-translate-y: -50%; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + .-translate-y-full { --tw-translate-y: -100%; transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); @@ -1963,6 +1995,16 @@ body { color: hsl(var(--muted-foreground) / var(--tw-text-opacity)); } +.before\:absolute::before { + content: var(--tw-content); + position: absolute; +} + +.before\:inset-0::before { + content: var(--tw-content); + inset: 0px; +} + .after\:absolute::after { content: var(--tw-content); position: absolute; @@ -2041,6 +2083,12 @@ body { --tw-ring-offset-width: 2px; } +.checked\:before\:bg-primary:checked::before { + content: var(--tw-content); + --tw-bg-opacity: 1; + background-color: hsl(var(--primary) / var(--tw-bg-opacity)); +} + .hover\:bg-accent:hover { --tw-bg-opacity: 1; background-color: hsl(var(--accent) / var(--tw-bg-opacity)); @@ -2134,6 +2182,22 @@ body { outline-offset: 2px; } +.focus\:outline:focus { + outline-style: solid; +} + +.focus\:outline-2:focus { + outline-width: 2px; +} + +.focus\:outline-offset-2:focus { + outline-offset: 2px; +} + +.focus\:outline-ring:focus { + outline-color: hsl(var(--ring) / 1); +} + .focus\:ring-2:focus { --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color); --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color); @@ -2158,6 +2222,10 @@ body { --tw-ring-offset-width: 2px; } +.checked\:focus\:outline-primary:focus:checked { + outline-color: hsl(var(--primary) / 1); +} + .focus-visible\:outline-none:focus-visible { outline: 2px solid transparent; outline-offset: 2px; @@ -2184,6 +2252,10 @@ body { --tw-ring-offset-width: 2px; } +.active\:outline-offset-0:active { + outline-offset: 0px; +} + .disabled\:pointer-events-none:disabled { pointer-events: none; } @@ -2214,6 +2286,10 @@ body { opacity: 1; } +.peer:checked ~ .peer-checked\:visible { + visibility: visible; +} + .peer:checked ~ .peer-checked\:bg-primary { --tw-bg-opacity: 1; background-color: hsl(var(--primary) / var(--tw-bg-opacity)); @@ -2236,21 +2312,6 @@ body { background-color: hsl(var(--secondary) / var(--tw-bg-opacity)); } -.peer:focus-visible ~ .peer-focus-visible\:ring-2 { - --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color); - --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color); - box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000); -} - -.peer:focus-visible ~ .peer-focus-visible\:ring-ring { - --tw-ring-opacity: 1; - --tw-ring-color: hsl(var(--ring) / var(--tw-ring-opacity)); -} - -.peer:focus-visible ~ .peer-focus-visible\:ring-offset-2 { - --tw-ring-offset-width: 2px; -} - .peer:disabled ~ .peer-disabled\:cursor-not-allowed { cursor: not-allowed; } @@ -2440,6 +2501,19 @@ body { } } +.\[\&\:has\(input\:checked\)\]\:text-foreground:has(input:checked) { + --tw-text-opacity: 1; + color: hsl(var(--foreground) / var(--tw-text-opacity)); +} + +.\[\&\:has\(input\:disabled\)\]\:cursor-not-allowed:has(input:disabled) { + cursor: not-allowed; +} + +.\[\&\:has\(input\:disabled\)\]\:opacity-50:has(input:disabled) { + opacity: 0.5; +} + .\[\&\:has\(svg\)\]\:pl-11:has(svg) { padding-left: 2.75rem; } diff --git a/internals/ui/showcase/checkbox.templ b/internals/ui/showcase/checkbox.templ index 783b6e0..bff7bff 100644 --- a/internals/ui/showcase/checkbox.templ +++ b/internals/ui/showcase/checkbox.templ @@ -17,32 +17,31 @@ templ CheckboxShowcase() {

Checked Checkbox

@components.Checkbox(components.CheckboxProps{ - ID: "checked-checkbox", - Name: "newsletter", - Value: "subscribe", - Label: "Receive newsletter", - Checked: "true", + ID: "checked-checkbox", + Name: "newsletter", + Value: "subscribe", + Label: "Receive newsletter", + Attributes: templ.Attributes{"checked": "true"}, })

Disabled Checkbox

@components.Checkbox(components.CheckboxProps{ - ID: "disabled-checkbox", - Name: "disabled", - Value: "disabled", - Label: "Disabled option", - Disabled: "true", + ID: "disabled-checkbox", + Name: "disabled", + Value: "disabled", + Label: "Disabled option", + Attributes: templ.Attributes{"disabled": "true"}, })

Disabled Checked Checkbox

@components.Checkbox(components.CheckboxProps{ - ID: "disabled-checked-checkbox", - Name: "disabled-checked", - Value: "disabled-checked", - Label: "Disabled checked option", - Checked: "true", - Disabled: "true", + ID: "disabled-checked-checkbox", + Name: "disabled-checked", + Value: "disabled-checked", + Label: "Disabled checked option", + Attributes: templ.Attributes{"checked": "true", "disabled": "true"}, })
diff --git a/pkg/components/checkbox.templ b/pkg/components/checkbox.templ index c197545..d30180a 100644 --- a/pkg/components/checkbox.templ +++ b/pkg/components/checkbox.templ @@ -1,10 +1,7 @@ package components -import ( - "fmt" - "github.com/axzilla/goilerplate/pkg/icons" - "github.com/axzilla/goilerplate/pkg/utils" -) +import "github.com/axzilla/goilerplate/pkg/utils" +import "github.com/axzilla/goilerplate/pkg/icons" // CheckboxProps defines the properties for the Checkbox component. type CheckboxProps struct { @@ -21,14 +18,6 @@ type CheckboxProps struct { // If empty, no label will be rendered. Label string - // Checked is a JavaScript expression for the checked state - // Example: "true", "isSubscribed", "5+5===10" - Checked string - - // Disabled is a JavaScript expression for the disabled state - // Example: "true", "isLoading", "!isEnabled" - Disabled string - // Class specifies additional CSS classes for the container Class string @@ -38,77 +27,51 @@ type CheckboxProps struct { // Checkbox renders a customizable checkbox component with an associated label. // -// Usage: -// -// @components.Checkbox(components.CheckboxProps{ -// ID: "terms", -// Name: "accept_terms", -// Value: "accepted", -// Label: "I accept the terms and conditions", -// Checked: "true", -// Disabled: "isSubmitting", -// Class: "mt-4", -// Attributes: templ.Attributes{"data-testid": "terms-checkbox"}, -// }) -// // Props: // - ID: The unique identifier for the checkbox input. Required. // - Name: The name attribute for the checkbox input. Required. // - Value: The value attribute for the checkbox input. Required. // - Label: The text label associated with the checkbox. Optional. -// - Checked: Determines the checked state. Can be a bool or a string for dynamic binding. Optional. -// - Disabled: Determines the disabled state. Can be a bool or a string for dynamic binding. Optional. // - Class: Additional CSS classes to apply to the checkbox container. Optional. // - Attributes: Additional HTML attributes to apply to the checkbox input element. Optional. +// CheckboxProps bleibt gleich, nur die Template-Implementierung ändert sich templ Checkbox(props CheckboxProps) { -
-
+
+ } diff --git a/pkg/components/checkbox_templ.go b/pkg/components/checkbox_templ.go index d1f078d..dbd02ea 100644 --- a/pkg/components/checkbox_templ.go +++ b/pkg/components/checkbox_templ.go @@ -8,11 +8,8 @@ package components import "github.com/a-h/templ" import templruntime "github.com/a-h/templ/runtime" -import ( - "fmt" - "github.com/axzilla/goilerplate/pkg/icons" - "github.com/axzilla/goilerplate/pkg/utils" -) +import "github.com/axzilla/goilerplate/pkg/utils" +import "github.com/axzilla/goilerplate/pkg/icons" // CheckboxProps defines the properties for the Checkbox component. type CheckboxProps struct { @@ -29,14 +26,6 @@ type CheckboxProps struct { // If empty, no label will be rendered. Label string - // Checked is a JavaScript expression for the checked state - // Example: "true", "isSubscribed", "5+5===10" - Checked string - - // Disabled is a JavaScript expression for the disabled state - // Example: "true", "isLoading", "!isEnabled" - Disabled string - // Class specifies additional CSS classes for the container Class string @@ -46,28 +35,15 @@ type CheckboxProps struct { // Checkbox renders a customizable checkbox component with an associated label. // -// Usage: -// -// @components.Checkbox(components.CheckboxProps{ -// ID: "terms", -// Name: "accept_terms", -// Value: "accepted", -// Label: "I accept the terms and conditions", -// Checked: "true", -// Disabled: "isSubmitting", -// Class: "mt-4", -// Attributes: templ.Attributes{"data-testid": "terms-checkbox"}, -// }) -// // Props: // - ID: The unique identifier for the checkbox input. Required. // - Name: The name attribute for the checkbox input. Required. // - Value: The value attribute for the checkbox input. Required. // - Label: The text label associated with the checkbox. Optional. -// - Checked: Determines the checked state. Can be a bool or a string for dynamic binding. Optional. -// - Disabled: Determines the disabled state. Can be a bool or a string for dynamic binding. Optional. // - Class: Additional CSS classes to apply to the checkbox container. Optional. // - Attributes: Additional HTML attributes to apply to the checkbox input element. Optional. +// +// CheckboxProps bleibt gleich, nur die Template-Implementierung ändert sich func Checkbox(props CheckboxProps) 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 @@ -89,47 +65,65 @@ func Checkbox(props CheckboxProps) templ.Component { templ_7745c5c3_Var1 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - var templ_7745c5c3_Var2 = []any{utils.TwMerge("flex items-center space-x-2", props.Class)} + var templ_7745c5c3_Var2 = []any{utils.TwMerge( + "flex cursor-pointer items-center gap-2 text-sm font-medium", + "text-muted-foreground [&:has(input:checked)]:text-foreground", + "[&:has(input:disabled)]:opacity-50 [&:has(input:disabled)]:cursor-not-allowed", + props.Class, + )} templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var2...) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(">
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - if props.Checked != "" { - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = icons.Check(icons.IconProps{Size: "12"}).Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } else { - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = icons.Check(icons.IconProps{Size: "12"}).Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } + templ_7745c5c3_Err = icons.Check(icons.IconProps{Size: "12"}).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if props.Label != "" { - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/pkg/styles/goilerplate.css b/pkg/styles/goilerplate.css index f0cebe3..9b66f51 100644 --- a/pkg/styles/goilerplate.css +++ b/pkg/styles/goilerplate.css @@ -645,6 +645,10 @@ body { pointer-events: none; } +.invisible { + visibility: hidden; +} + .static { position: static; } @@ -691,6 +695,10 @@ body { left: 0px; } +.left-1\/2 { + left: 50%; +} + .left-2 { left: 0.5rem; } @@ -711,6 +719,10 @@ body { top: 0px; } +.top-1\/2 { + top: 50%; +} + .top-2 { top: 0.5rem; } @@ -812,6 +824,16 @@ body { aspect-ratio: 1 / 1; } +.size-3 { + width: 0.75rem; + height: 0.75rem; +} + +.size-4 { + width: 1rem; + height: 1rem; +} + .h-1\/2 { height: 50%; } @@ -940,11 +962,21 @@ body { flex-shrink: 1; } +.-translate-x-1\/2 { + --tw-translate-x: -50%; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + .-translate-x-full { --tw-translate-x: -100%; transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); } +.-translate-y-1\/2 { + --tw-translate-y: -50%; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + .-translate-y-full { --tw-translate-y: -100%; transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); @@ -1701,6 +1733,16 @@ body { color: hsl(var(--muted-foreground) / var(--tw-text-opacity)); } +.before\:absolute::before { + content: var(--tw-content); + position: absolute; +} + +.before\:inset-0::before { + content: var(--tw-content); + inset: 0px; +} + .after\:absolute::after { content: var(--tw-content); position: absolute; @@ -1779,6 +1821,12 @@ body { --tw-ring-offset-width: 2px; } +.checked\:before\:bg-primary:checked::before { + content: var(--tw-content); + --tw-bg-opacity: 1; + background-color: hsl(var(--primary) / var(--tw-bg-opacity)); +} + .hover\:bg-accent:hover { --tw-bg-opacity: 1; background-color: hsl(var(--accent) / var(--tw-bg-opacity)); @@ -1853,6 +1901,22 @@ body { outline-offset: 2px; } +.focus\:outline:focus { + outline-style: solid; +} + +.focus\:outline-2:focus { + outline-width: 2px; +} + +.focus\:outline-offset-2:focus { + outline-offset: 2px; +} + +.focus\:outline-ring:focus { + outline-color: hsl(var(--ring) / 1); +} + .focus\:ring-2:focus { --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color); --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color); @@ -1877,6 +1941,10 @@ body { --tw-ring-offset-width: 2px; } +.checked\:focus\:outline-primary:focus:checked { + outline-color: hsl(var(--primary) / 1); +} + .focus-visible\:outline-none:focus-visible { outline: 2px solid transparent; outline-offset: 2px; @@ -1897,6 +1965,10 @@ body { --tw-ring-offset-width: 2px; } +.active\:outline-offset-0:active { + outline-offset: 0px; +} + .disabled\:pointer-events-none:disabled { pointer-events: none; } @@ -1927,6 +1999,10 @@ body { opacity: 1; } +.peer:checked ~ .peer-checked\:visible { + visibility: visible; +} + .peer:checked ~ .peer-checked\:bg-primary { --tw-bg-opacity: 1; background-color: hsl(var(--primary) / var(--tw-bg-opacity)); @@ -1949,21 +2025,6 @@ body { background-color: hsl(var(--secondary) / var(--tw-bg-opacity)); } -.peer:focus-visible ~ .peer-focus-visible\:ring-2 { - --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color); - --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color); - box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000); -} - -.peer:focus-visible ~ .peer-focus-visible\:ring-ring { - --tw-ring-opacity: 1; - --tw-ring-color: hsl(var(--ring) / var(--tw-ring-opacity)); -} - -.peer:focus-visible ~ .peer-focus-visible\:ring-offset-2 { - --tw-ring-offset-width: 2px; -} - .peer:disabled ~ .peer-disabled\:cursor-not-allowed { cursor: not-allowed; } @@ -2052,6 +2113,19 @@ body { } } +.\[\&\:has\(input\:checked\)\]\:text-foreground:has(input:checked) { + --tw-text-opacity: 1; + color: hsl(var(--foreground) / var(--tw-text-opacity)); +} + +.\[\&\:has\(input\:disabled\)\]\:cursor-not-allowed:has(input:disabled) { + cursor: not-allowed; +} + +.\[\&\:has\(input\:disabled\)\]\:opacity-50:has(input:disabled) { + opacity: 0.5; +} + .\[\&\:has\(svg\)\]\:pl-11:has(svg) { padding-left: 2.75rem; } From b888af999a445c5434bbc9002833e1df085a104e Mon Sep 17 00:00:00 2001 From: axzilla Date: Tue, 19 Nov 2024 15:45:08 +0700 Subject: [PATCH 04/17] change: simplify radiogroup component --- assets/css/output.css | 174 +++++++++++++++ internals/ui/pages/themes.templ | 42 ++-- internals/ui/showcase/radio_group.templ | 50 ++--- pkg/components/accordion_templ.go | 20 +- pkg/components/alert_templ.go | 14 +- pkg/components/avatar_templ.go | 18 +- pkg/components/button_templ.go | 42 ++-- pkg/components/card_templ.go | 28 +-- pkg/components/checkbox_templ.go | 22 +- pkg/components/datepicker_templ.go | 20 +- pkg/components/dropdown_menu_templ.go | 70 +++--- pkg/components/footer_templ.go | 4 +- pkg/components/form_templ.go | 16 +- pkg/components/input_templ.go | 24 +- pkg/components/modal_templ.go | 34 +-- pkg/components/navbar_templ.go | 28 +-- pkg/components/radio_group.templ | 91 +++----- pkg/components/radio_group_templ.go | 280 +++++++----------------- pkg/components/select_templ.go | 62 +++--- pkg/components/sheet_templ.go | 38 ++-- pkg/components/sidebar_right_templ.go | 18 +- pkg/components/sidebar_templ.go | 16 +- pkg/components/tabs_templ.go | 22 +- pkg/components/themeswitcher_templ.go | 6 +- pkg/components/toggle_templ.go | 22 +- pkg/styles/goilerplate.css | 170 ++++++++++++++ 26 files changed, 762 insertions(+), 569 deletions(-) diff --git a/assets/css/output.css b/assets/css/output.css index 0b680fd..e332f32 100644 --- a/assets/css/output.css +++ b/assets/css/output.css @@ -1010,6 +1010,15 @@ body { width: 100%; } +.w-fit { + width: -moz-fit-content; + width: fit-content; +} + +.min-w-\[14rem\] { + min-width: 14rem; +} + .max-w-3xl { max-width: 48rem; } @@ -1185,6 +1194,10 @@ body { grid-template-columns: repeat(7, minmax(0, 1fr)); } +.flex-row { + flex-direction: row; +} + .flex-col { flex-direction: column; } @@ -1336,6 +1349,10 @@ body { border-radius: calc(var(--radius) - 4px); } +.rounded-none { + border-radius: 0px; +} + .border { border-width: 1px; } @@ -1344,6 +1361,10 @@ body { border-width: 2px; } +.border-4 { + border-width: 4px; +} + .border-b { border-bottom-width: 1px; } @@ -1484,6 +1505,16 @@ body { background-color: rgb(255 255 255 / var(--tw-bg-opacity)); } +.bg-stone-200 { + --tw-bg-opacity: 1; + background-color: rgb(231 229 228 / var(--tw-bg-opacity)); +} + +.bg-stone-50 { + --tw-bg-opacity: 1; + background-color: rgb(250 250 249 / var(--tw-bg-opacity)); +} + .bg-opacity-50 { --tw-bg-opacity: 0.5; } @@ -1805,6 +1836,11 @@ body { color: rgb(255 255 255 / var(--tw-text-opacity)); } +.text-stone-800 { + --tw-text-opacity: 1; + color: rgb(41 37 36 / var(--tw-text-opacity)); +} + .underline { text-decoration-line: underline; } @@ -1995,6 +2031,11 @@ body { color: hsl(var(--muted-foreground) / var(--tw-text-opacity)); } +.before\:invisible::before { + content: var(--tw-content); + visibility: hidden; +} + .before\:absolute::before { content: var(--tw-content); position: absolute; @@ -2005,6 +2046,71 @@ body { inset: 0px; } +.before\:left-1\/2::before { + content: var(--tw-content); + left: 50%; +} + +.before\:top-1\/2::before { + content: var(--tw-content); + top: 50%; +} + +.before\:h-1\.5::before { + content: var(--tw-content); + height: 0.375rem; +} + +.before\:h-2::before { + content: var(--tw-content); + height: 0.5rem; +} + +.before\:w-1\.5::before { + content: var(--tw-content); + width: 0.375rem; +} + +.before\:w-2::before { + content: var(--tw-content); + width: 0.5rem; +} + +.before\:-translate-x-1\/2::before { + content: var(--tw-content); + --tw-translate-x: -50%; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.before\:-translate-y-1\/2::before { + content: var(--tw-content); + --tw-translate-y: -50%; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.before\:rounded-full::before { + content: var(--tw-content); + border-radius: 9999px; +} + +.before\:bg-primary-foreground::before { + content: var(--tw-content); + --tw-bg-opacity: 1; + background-color: hsl(var(--primary-foreground) / var(--tw-bg-opacity)); +} + +.before\:bg-black::before { + content: var(--tw-content); + --tw-bg-opacity: 1; + background-color: rgb(0 0 0 / var(--tw-bg-opacity)); +} + +.before\:bg-background::before { + content: var(--tw-content); + --tw-bg-opacity: 1; + background-color: hsl(var(--background) / var(--tw-bg-opacity)); +} + .after\:absolute::after { content: var(--tw-content); position: absolute; @@ -2063,6 +2169,11 @@ body { background-color: hsl(var(--primary) / var(--tw-bg-opacity)); } +.checked\:bg-amber-500:checked { + --tw-bg-opacity: 1; + background-color: rgb(245 158 11 / var(--tw-bg-opacity)); +} + .checked\:outline-none:checked { outline: 2px solid transparent; outline-offset: 2px; @@ -2083,6 +2194,11 @@ body { --tw-ring-offset-width: 2px; } +.checked\:before\:visible:checked::before { + content: var(--tw-content); + visibility: visible; +} + .checked\:before\:bg-primary:checked::before { content: var(--tw-content); --tw-bg-opacity: 1; @@ -2198,6 +2314,10 @@ body { outline-color: hsl(var(--ring) / 1); } +.focus\:outline-blue-600:focus { + outline-color: #2563eb; +} + .focus\:ring-2:focus { --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color); --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color); @@ -2226,6 +2346,10 @@ body { outline-color: hsl(var(--primary) / 1); } +.checked\:focus\:outline-amber-500:focus:checked { + outline-color: #f59e0b; +} + .focus-visible\:outline-none:focus-visible { outline: 2px solid transparent; outline-offset: 2px; @@ -2252,6 +2376,10 @@ body { --tw-ring-offset-width: 2px; } +.focus-visible\:ring-offset-background:focus-visible { + --tw-ring-offset-color: hsl(var(--background) / 1); +} + .active\:outline-offset-0:active { outline-offset: 0px; } @@ -2324,6 +2452,20 @@ body { opacity: 0.7; } +.has-\[\:disabled\]\:opacity-75:has(:disabled) { + opacity: 0.75; +} + +.dark\:bg-stone-900:is(.dark *) { + --tw-bg-opacity: 1; + background-color: rgb(28 25 23 / var(--tw-bg-opacity)); +} + +.dark\:bg-stone-950:is(.dark *) { + --tw-bg-opacity: 1; + background-color: rgb(12 10 9 / var(--tw-bg-opacity)); +} + .dark\:from-gray-900:is(.dark *) { --tw-gradient-from: #111827 var(--tw-gradient-from-position); --tw-gradient-to: rgb(17 24 39 / 0) var(--tw-gradient-to-position); @@ -2354,16 +2496,40 @@ body { color: rgb(255 255 255 / var(--tw-text-opacity)); } +.dark\:text-stone-300:is(.dark *) { + --tw-text-opacity: 1; + color: rgb(214 211 209 / var(--tw-text-opacity)); +} + .dark\:file\:text-foreground:is(.dark *)::file-selector-button { --tw-text-opacity: 1; color: hsl(var(--foreground) / var(--tw-text-opacity)); } +.dark\:before\:bg-black:is(.dark *)::before { + content: var(--tw-content); + --tw-bg-opacity: 1; + background-color: rgb(0 0 0 / var(--tw-bg-opacity)); +} + +.dark\:checked\:bg-amber-400:checked:is(.dark *) { + --tw-bg-opacity: 1; + background-color: rgb(251 191 36 / var(--tw-bg-opacity)); +} + .dark\:hover\:bg-gray-700:hover:is(.dark *) { --tw-bg-opacity: 1; background-color: rgb(55 65 81 / var(--tw-bg-opacity)); } +.dark\:focus\:outline-blue-500:focus:is(.dark *) { + outline-color: #3b82f6; +} + +.dark\:checked\:focus\:outline-amber-400:focus:checked:is(.dark *) { + outline-color: #fbbf24; +} + @media (min-width: 640px) { .sm\:my-8 { margin-top: 2rem; @@ -2501,6 +2667,14 @@ body { } } +.\[\&\:has\(\:disabled\)\]\:cursor-not-allowed:has(:disabled) { + cursor: not-allowed; +} + +.\[\&\:has\(\:disabled\)\]\:opacity-50:has(:disabled) { + opacity: 0.5; +} + .\[\&\:has\(input\:checked\)\]\:text-foreground:has(input:checked) { --tw-text-opacity: 1; color: hsl(var(--foreground) / var(--tw-text-opacity)); diff --git a/internals/ui/pages/themes.templ b/internals/ui/pages/themes.templ index 68c8fec..04a6134 100644 --- a/internals/ui/pages/themes.templ +++ b/internals/ui/pages/themes.templ @@ -103,28 +103,26 @@ templ ThemePreview() {
- @components.RadioGroup(components.RadioGroupProps{Value: "email", Name: "contact-method"}) { -
- @components.RadioGroupItem(components.RadioGroupItemProps{ - Value: "email", - ID: "contact-email", - Name: "contact-method", - Label: templ.Raw("Email"), - }) - @components.RadioGroupItem(components.RadioGroupItemProps{ - Value: "phone", - ID: "contact-phone", - Name: "contact-method", - Label: templ.Raw("Phone"), - }) - @components.RadioGroupItem(components.RadioGroupItemProps{ - Value: "mail", - ID: "contact-mail", - Name: "contact-method", - Label: templ.Raw("Physical Mail"), - Disabled: "true", - }) -
+ @components.RadioGroup(components.RadioGroupProps{Name: "contact-method"}) { + @components.RadioGroupItem(components.RadioGroupItemProps{ + Value: "email", + ID: "contact-email", + Name: "contact-method", + Label: templ.Raw("Email"), + }) + @components.RadioGroupItem(components.RadioGroupItemProps{ + Value: "phone", + ID: "contact-phone", + Name: "contact-method", + Label: templ.Raw("Phone"), + }) + @components.RadioGroupItem(components.RadioGroupItemProps{ + Value: "mail", + ID: "contact-mail", + Name: "contact-method", + Label: templ.Raw("Physical Mail"), + Attributes: templ.Attributes{"disabled": "true"}, + }) }
diff --git a/internals/ui/showcase/radio_group.templ b/internals/ui/showcase/radio_group.templ index a5dc669..ba78a7d 100644 --- a/internals/ui/showcase/radio_group.templ +++ b/internals/ui/showcase/radio_group.templ @@ -4,33 +4,27 @@ import "github.com/axzilla/goilerplate/pkg/components" templ RadioGroupShowcase() {
-
- @components.RadioGroup(components.RadioGroupProps{Value: "'default'", Name: "view-mode"}) { -
- @components.RadioGroupItem(components.RadioGroupItemProps{ - Value: "default", - ID: "r1", - Name: "view-mode", - Label: templ.Raw("Default"), - Attributes: templ.Attributes{"x-model": "checked"}, - }) - @components.RadioGroupItem(components.RadioGroupItemProps{ - Value: "comfortable", - ID: "r2", - Name: "view-mode", - Disabled: "true", - Label: templ.Raw("Comfortable"), - Attributes: templ.Attributes{"x-model": "checked"}, - }) - @components.RadioGroupItem(components.RadioGroupItemProps{ - Value: "compact", - ID: "r3", - Name: "view-mode", - Label: templ.Raw("Compact"), - Attributes: templ.Attributes{"x-model": "checked"}, - }) -
- } -
+ @components.RadioGroup(components.RadioGroupProps{}) { + @components.RadioGroupItem(components.RadioGroupItemProps{ + Value: "default", + ID: "r1", + Name: "view-mode", + Label: templ.Raw("Default"), + Attributes: templ.Attributes{"checked": true}, + }) + @components.RadioGroupItem(components.RadioGroupItemProps{ + Value: "comfortable", + ID: "r2", + Name: "view-mode", + Label: templ.Raw("Disabled"), + Attributes: templ.Attributes{"disabled": true}, + }) + @components.RadioGroupItem(components.RadioGroupItemProps{ + Value: "compact", + ID: "r3", + Name: "view-mode", + Label: templ.Raw("Compact"), + }) + }
} diff --git a/pkg/components/accordion_templ.go b/pkg/components/accordion_templ.go index 922647c..f549345 100644 --- a/pkg/components/accordion_templ.go +++ b/pkg/components/accordion_templ.go @@ -94,7 +94,7 @@ func Accordion(props AccordionProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 3) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } for _, item := range props.Items { - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("

") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 8) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -179,12 +179,12 @@ func Accordion(props AccordionProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 9) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 10) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/pkg/components/alert_templ.go b/pkg/components/alert_templ.go index 198bafe..89dc2da 100644 --- a/pkg/components/alert_templ.go +++ b/pkg/components/alert_templ.go @@ -86,7 +86,7 @@ func Alert(props AlertProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 2) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -107,7 +107,7 @@ func Alert(props AlertProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 3) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -137,7 +137,7 @@ func AlertTitle() templ.Component { templ_7745c5c3_Var4 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 4) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -145,7 +145,7 @@ func AlertTitle() templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 5) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -175,7 +175,7 @@ func AlertDescription() templ.Component { templ_7745c5c3_Var5 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 6) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -183,7 +183,7 @@ func AlertDescription() templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 7) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/pkg/components/avatar_templ.go b/pkg/components/avatar_templ.go index 6b72e11..459ecc2 100644 --- a/pkg/components/avatar_templ.go +++ b/pkg/components/avatar_templ.go @@ -120,7 +120,7 @@ func Avatar(props AvatarProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 3) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if props.ImageSrc != "" { - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"")") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 6) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } else { - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 7) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -190,12 +190,12 @@ func Avatar(props AvatarProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 8) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 9) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/pkg/components/button_templ.go b/pkg/components/button_templ.go index 078b233..1419f76 100644 --- a/pkg/components/button_templ.go +++ b/pkg/components/button_templ.go @@ -193,7 +193,7 @@ func Button(props ButtonProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 8) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -275,7 +275,7 @@ func Button(props ButtonProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 9) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -295,7 +295,7 @@ func Button(props ButtonProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 18) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -407,7 +407,7 @@ func renderButtonContent(props ButtonProps) templ.Component { templ_7745c5c3_Var11 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 19) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -426,7 +426,7 @@ func renderButtonContent(props ButtonProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 20) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -436,7 +436,7 @@ func renderButtonContent(props ButtonProps) templ.Component { return templ_7745c5c3_Err } } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 21) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/pkg/components/card_templ.go b/pkg/components/card_templ.go index 72f4ffb..3ed747a 100644 --- a/pkg/components/card_templ.go +++ b/pkg/components/card_templ.go @@ -62,7 +62,7 @@ func Card(props CardProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 3) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -91,7 +91,7 @@ func Card(props CardProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 4) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -128,7 +128,7 @@ func CardHeader() templ.Component { templ_7745c5c3_Var4 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 5) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -136,7 +136,7 @@ func CardHeader() templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 6) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -172,7 +172,7 @@ func CardTitle() templ.Component { templ_7745c5c3_Var5 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("

") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 7) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -180,7 +180,7 @@ func CardTitle() templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("

") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 8) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -216,7 +216,7 @@ func CardDescription() templ.Component { templ_7745c5c3_Var6 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("

") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 9) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -224,7 +224,7 @@ func CardDescription() templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("

") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 10) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -260,7 +260,7 @@ func CardContent() templ.Component { templ_7745c5c3_Var7 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 11) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -268,7 +268,7 @@ func CardContent() templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 12) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -304,7 +304,7 @@ func CardFooter() templ.Component { templ_7745c5c3_Var8 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 13) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -312,7 +312,7 @@ func CardFooter() templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 14) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/pkg/components/checkbox_templ.go b/pkg/components/checkbox_templ.go index dbd02ea..37a49dd 100644 --- a/pkg/components/checkbox_templ.go +++ b/pkg/components/checkbox_templ.go @@ -75,7 +75,7 @@ func Checkbox(props CheckboxProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 11) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/pkg/components/datepicker_templ.go b/pkg/components/datepicker_templ.go index 8eaafda..199c39f 100644 --- a/pkg/components/datepicker_templ.go +++ b/pkg/components/datepicker_templ.go @@ -82,7 +82,7 @@ func Datepicker(props DatepickerProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 7) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -163,7 +163,7 @@ func Datepicker(props DatepickerProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 10) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/pkg/components/dropdown_menu_templ.go b/pkg/components/dropdown_menu_templ.go index 91f3fff..d76ea5f 100644 --- a/pkg/components/dropdown_menu_templ.go +++ b/pkg/components/dropdown_menu_templ.go @@ -72,7 +72,7 @@ func renderMenuItem(item DropdownMenuItem, index int, depth int) templ.Component } ctx = templ.ClearChildren(ctx) if len(item.SubItems) > 0 { - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 1) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -86,7 +86,7 @@ func renderMenuItem(item DropdownMenuItem, index int, depth int) templ.Component if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 8) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if depth < 3 { - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 10) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 11) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -194,7 +194,7 @@ func renderMenuItem(item DropdownMenuItem, index int, depth int) templ.Component if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 17) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -269,12 +269,12 @@ func renderMenuItem(item DropdownMenuItem, index int, depth int) templ.Component if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 18) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if item.IconRight != nil { - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 19) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -282,12 +282,12 @@ func renderMenuItem(item DropdownMenuItem, index int, depth int) templ.Component if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 20) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 21) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -301,7 +301,7 @@ func renderMenuItem(item DropdownMenuItem, index int, depth int) templ.Component if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 28) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -440,7 +440,7 @@ func DropdownMenu(props DropdownMenuProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 31) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -485,7 +485,7 @@ func DropdownMenu(props DropdownMenuProps) templ.Component { return templ_7745c5c3_Err } } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 32) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -497,7 +497,7 @@ func DropdownMenu(props DropdownMenuProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 34) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -520,7 +520,7 @@ func DropdownMenu(props DropdownMenuProps) templ.Component { return templ_7745c5c3_Err } } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 35) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/pkg/components/footer_templ.go b/pkg/components/footer_templ.go index e4841e9..32fc075 100644 --- a/pkg/components/footer_templ.go +++ b/pkg/components/footer_templ.go @@ -32,7 +32,7 @@ func Footer() templ.Component { templ_7745c5c3_Var1 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("

") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 1) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -45,7 +45,7 @@ func Footer() templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" Stupid code not excluded.

") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 2) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/pkg/components/form_templ.go b/pkg/components/form_templ.go index 27df1c9..26db1ab 100644 --- a/pkg/components/form_templ.go +++ b/pkg/components/form_templ.go @@ -64,7 +64,7 @@ func Form[T FormDataProvider](props FormProps[T]) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 6) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -143,7 +143,7 @@ func Form[T FormDataProvider](props FormProps[T]) templ.Component { return templ_7745c5c3_Err } } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 7) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -173,7 +173,7 @@ func FormDebug() templ.Component { templ_7745c5c3_Var7 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("

Form Debug

Form Data:

Errors:

State:

Submitting:
Submitted:
") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 8) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/pkg/components/input_templ.go b/pkg/components/input_templ.go index 6482e64..cc6a909 100644 --- a/pkg/components/input_templ.go +++ b/pkg/components/input_templ.go @@ -127,7 +127,7 @@ func Input(props InputProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 12) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/pkg/components/modal_templ.go b/pkg/components/modal_templ.go index 8700b11..3d04ab2 100644 --- a/pkg/components/modal_templ.go +++ b/pkg/components/modal_templ.go @@ -76,7 +76,7 @@ func Modal(props ModalProps) templ.Component { templ_7745c5c3_Var1 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 2) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -102,7 +102,7 @@ func Modal(props ModalProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 4) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -123,7 +123,7 @@ func Modal(props ModalProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 5) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -161,7 +161,7 @@ func ModalTrigger(id string) templ.Component { templ_7745c5c3_Var5 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 7) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -182,7 +182,7 @@ func ModalTrigger(id string) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 8) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -223,7 +223,7 @@ func ModalClose(id string) templ.Component { templ_7745c5c3_Var7 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 10) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -244,7 +244,7 @@ func ModalClose(id string) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 11) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -281,7 +281,7 @@ func ModalHeader() templ.Component { templ_7745c5c3_Var9 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("

") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 12) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -289,7 +289,7 @@ func ModalHeader() templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("

") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 13) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -325,7 +325,7 @@ func ModalBody() templ.Component { templ_7745c5c3_Var10 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 14) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -333,7 +333,7 @@ func ModalBody() templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 15) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -374,7 +374,7 @@ func ModalFooter() templ.Component { templ_7745c5c3_Var11 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 16) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -382,7 +382,7 @@ func ModalFooter() templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 17) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/pkg/components/navbar_templ.go b/pkg/components/navbar_templ.go index 1f34cbe..79c0e3f 100644 --- a/pkg/components/navbar_templ.go +++ b/pkg/components/navbar_templ.go @@ -34,7 +34,7 @@ func Navbar() templ.Component { templ_7745c5c3_Var1 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 3) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -112,7 +112,7 @@ func NavbarMobileMenu() templ.Component { } ctx = templ.InitializeContext(ctx) for _, section := range shared.Sections { - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("

") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 4) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -125,12 +125,12 @@ func NavbarMobileMenu() templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("

") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 11) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -191,7 +191,7 @@ func NavbarMobileMenu() templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 12) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -207,7 +207,7 @@ func NavbarMobileMenu() templ.Component { }() } ctx = templ.InitializeContext(ctx) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 14) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/pkg/components/radio_group.templ b/pkg/components/radio_group.templ index 7fb4e4e..d240be0 100644 --- a/pkg/components/radio_group.templ +++ b/pkg/components/radio_group.templ @@ -1,25 +1,13 @@ package components -import ( - "fmt" - "github.com/axzilla/goilerplate/pkg/utils" -) +import "github.com/axzilla/goilerplate/pkg/utils" // RadioGroupProps defines the properties for the RadioGroup component. type RadioGroupProps struct { - // Value is the Alpine.js x-model binding expression - // Example: "formData.marketingConsent" - Value string - // Name is the name attribute for the radio group Name string - - // Required indicates if the radio group must have a selection - Required bool - // Class specifies additional CSS classes Class string - // Attributes allows passing additional HTML attributes Attributes templ.Attributes } @@ -28,47 +16,35 @@ type RadioGroupProps struct { type RadioGroupItemProps struct { // Value is the value attribute for the radio button Value string - // Name is the name attribute, should match the RadioGroup's name Name string - // ID is the unique identifier for the radio button ID string - - // Disabled is an Alpine.js expression for the disabled state - // Examples: - // - "true" for always disabled - // - "formData.isLoading" for dynamic state - // - "user.role !== 'admin'" for conditional disabling - Disabled string - + // Label is the text label displayed next to the radio button + Label templ.Component // Class specifies additional CSS classes Class string - // Attributes allows passing additional HTML attributes Attributes templ.Attributes - - // Label is the templ.Component to use as the radio button's label - Label templ.Component } -// RadioGroup renders a group of radio buttons with shared state management. +// RadioGroup renders a group of radio buttons with shared name attribute. // // Usage: // // @components.RadioGroup(components.RadioGroupProps{ // Name: "marketing", -// Value: "formData.marketingConsent", -// DefaultValue: "email", -// Required: true, // }) { -// // RadioGroup items go here +// @components.RadioGroupItem(components.RadioGroupItemProps{ +// Value: "email", +// Name: "marketing", +// ID: "marketing-email", +// Label: templ.Raw("Email Marketing"), +// }) // } templ RadioGroup(props RadioGroupProps) {
@@ -77,7 +53,6 @@ templ RadioGroup(props RadioGroupProps) { } // RadioGroupItem renders a single radio button with an integrated label. -// It uses Alpine.js for state management and accessibility features. // // Usage: // @@ -85,37 +60,39 @@ templ RadioGroup(props RadioGroupProps) { // Value: "email", // Name: "marketing", // ID: "marketing-email", -// Disabled: "isLoading", // Label: templ.Raw("Email Marketing"), +// Attributes: templ.Attributes{"checked": selectedOption == "email"}, // }) templ RadioGroupItem(props RadioGroupItemProps) { -
- -
+ if props.Label != nil { + @props.Label + } else { + { props.Value } + } + } diff --git a/pkg/components/radio_group_templ.go b/pkg/components/radio_group_templ.go index 34de3ae..9ddaaae 100644 --- a/pkg/components/radio_group_templ.go +++ b/pkg/components/radio_group_templ.go @@ -8,26 +8,14 @@ package components import "github.com/a-h/templ" import templruntime "github.com/a-h/templ/runtime" -import ( - "fmt" - "github.com/axzilla/goilerplate/pkg/utils" -) +import "github.com/axzilla/goilerplate/pkg/utils" // RadioGroupProps defines the properties for the RadioGroup component. type RadioGroupProps struct { - // Value is the Alpine.js x-model binding expression - // Example: "formData.marketingConsent" - Value string - // Name is the name attribute for the radio group Name string - - // Required indicates if the radio group must have a selection - Required bool - // Class specifies additional CSS classes Class string - // Attributes allows passing additional HTML attributes Attributes templ.Attributes } @@ -36,41 +24,31 @@ type RadioGroupProps struct { type RadioGroupItemProps struct { // Value is the value attribute for the radio button Value string - // Name is the name attribute, should match the RadioGroup's name Name string - // ID is the unique identifier for the radio button ID string - - // Disabled is an Alpine.js expression for the disabled state - // Examples: - // - "true" for always disabled - // - "formData.isLoading" for dynamic state - // - "user.role !== 'admin'" for conditional disabling - Disabled string - + // Label is the text label displayed next to the radio button + Label templ.Component // Class specifies additional CSS classes Class string - // Attributes allows passing additional HTML attributes Attributes templ.Attributes - - // Label is the templ.Component to use as the radio button's label - Label templ.Component } -// RadioGroup renders a group of radio buttons with shared state management. +// RadioGroup renders a group of radio buttons with shared name attribute. // // Usage: // // @components.RadioGroup(components.RadioGroupProps{ // Name: "marketing", -// Value: "formData.marketingConsent", -// DefaultValue: "email", -// Required: true, // }) { -// // RadioGroup items go here +// @components.RadioGroupItem(components.RadioGroupItemProps{ +// Value: "email", +// Name: "marketing", +// ID: "marketing-email", +// Label: templ.Raw("Email Marketing"), +// }) // } func RadioGroup(props RadioGroupProps) templ.Component { return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { @@ -98,46 +76,20 @@ func RadioGroup(props RadioGroupProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 3) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -153,7 +105,7 @@ func RadioGroup(props RadioGroupProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 4) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -162,7 +114,6 @@ func RadioGroup(props RadioGroupProps) templ.Component { } // RadioGroupItem renders a single radio button with an integrated label. -// It uses Alpine.js for state management and accessibility features. // // Usage: // @@ -170,8 +121,8 @@ func RadioGroup(props RadioGroupProps) templ.Component { // Value: "email", // Name: "marketing", // ID: "marketing-email", -// Disabled: "isLoading", // Label: templ.Raw("Email Marketing"), +// Attributes: templ.Attributes{"checked": selectedOption == "email"}, // }) func RadioGroupItem(props RadioGroupItemProps) templ.Component { return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { @@ -189,130 +140,86 @@ func RadioGroupItem(props RadioGroupItemProps) templ.Component { }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var6 := templ.GetChildren(ctx) - if templ_7745c5c3_Var6 == nil { - templ_7745c5c3_Var6 = templ.NopComponent + templ_7745c5c3_Var4 := templ.GetChildren(ctx) + if templ_7745c5c3_Var4 == nil { + templ_7745c5c3_Var4 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - var templ_7745c5c3_Var7 = []any{utils.TwMerge("flex items-center space-x-2", props.Class)} - templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var7...) + var templ_7745c5c3_Var5 = []any{utils.TwMerge( + "flex items-center gap-2", + "[&:has(:disabled)]:cursor-not-allowed [&:has(:disabled)]:opacity-50", + props.Class, + )} + templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var5...) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 9) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var10 = []any{"h-4 w-4 translate-y-px appearance-none rounded-full border bg-background", - "checked:border-primary checked:bg-primary", - "disabled:opacity-50 disabled:cursor-not-allowed", - "checked:outline-none checked:ring-2 checked:ring-ring checked:ring-offset-2"} - templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var10...) + var templ_7745c5c3_Var10 string + templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(props.Value) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/components/radio_group.templ`, Line: 79, Col: 22} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var16 = []any{"text-sm font-medium leading-none text-foreground", templ.KV("opacity-50 cursor-not-allowed", props.Disabled)} - templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var16...) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 14) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/pkg/components/select_templ.go b/pkg/components/select_templ.go index 79e614d..874e91f 100644 --- a/pkg/components/select_templ.go +++ b/pkg/components/select_templ.go @@ -109,7 +109,7 @@ func Select(props SelectProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 18) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -294,7 +294,7 @@ func Select(props SelectProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
    ") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 24) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -353,7 +353,7 @@ func Select(props SelectProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
  • ") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 27) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -392,7 +392,7 @@ func Select(props SelectProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 29) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -413,12 +413,12 @@ func Select(props SelectProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
  • ") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 30) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 31) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/pkg/components/sheet_templ.go b/pkg/components/sheet_templ.go index c9885b9..bcf5a04 100644 --- a/pkg/components/sheet_templ.go +++ b/pkg/components/sheet_templ.go @@ -62,7 +62,7 @@ func SheetRoot() templ.Component { templ_7745c5c3_Var1 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 1) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -70,7 +70,7 @@ func SheetRoot() templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 2) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -115,35 +115,35 @@ func Sheet(props SheetProps) templ.Component { templ_7745c5c3_Var2 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 8) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -156,7 +156,7 @@ func Sheet(props SheetProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("

") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 10) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -182,7 +182,7 @@ func Sheet(props SheetProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("

") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 11) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -195,7 +195,7 @@ func Sheet(props SheetProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("

") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 12) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -203,7 +203,7 @@ func Sheet(props SheetProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 13) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -243,7 +243,7 @@ func SheetTrigger(text string, side SheetSide) templ.Component { templ_7745c5c3_Var7 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 15) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -264,7 +264,7 @@ func SheetTrigger(text string, side SheetSide) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 16) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -309,7 +309,7 @@ func SheetClose(text string) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 19) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/pkg/components/sidebar_right_templ.go b/pkg/components/sidebar_right_templ.go index d98e40f..a9528ed 100644 --- a/pkg/components/sidebar_right_templ.go +++ b/pkg/components/sidebar_right_templ.go @@ -55,12 +55,12 @@ func SidebarRight() templ.Component { templ_7745c5c3_Var1 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 9) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/pkg/components/sidebar_templ.go b/pkg/components/sidebar_templ.go index 23584a0..455248c 100644 --- a/pkg/components/sidebar_templ.go +++ b/pkg/components/sidebar_templ.go @@ -31,12 +31,12 @@ func Sidebar() templ.Component { templ_7745c5c3_Var1 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 8) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/pkg/components/tabs_templ.go b/pkg/components/tabs_templ.go index 0a1dce4..9a27594 100644 --- a/pkg/components/tabs_templ.go +++ b/pkg/components/tabs_templ.go @@ -73,7 +73,7 @@ func Tabs(props TabsProps) templ.Component { templ_7745c5c3_Var1 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 1) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -84,7 +84,7 @@ func Tabs(props TabsProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 3) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } for _, tab := range props.Tabs { - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 5) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 6) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -129,7 +129,7 @@ func Tabs(props TabsProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 8) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } for _, tab := range props.Tabs { - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 9) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -155,12 +155,12 @@ func Tabs(props TabsProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 10) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 11) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/pkg/components/themeswitcher_templ.go b/pkg/components/themeswitcher_templ.go index e57fd17..972fe45 100644 --- a/pkg/components/themeswitcher_templ.go +++ b/pkg/components/themeswitcher_templ.go @@ -67,7 +67,7 @@ func DynamicThemeIcon() templ.Component { templ_7745c5c3_Var2 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 1) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -75,7 +75,7 @@ func DynamicThemeIcon() templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 2) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -83,7 +83,7 @@ func DynamicThemeIcon() templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 3) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/pkg/components/toggle_templ.go b/pkg/components/toggle_templ.go index d24c9cd..bdcbbda 100644 --- a/pkg/components/toggle_templ.go +++ b/pkg/components/toggle_templ.go @@ -67,7 +67,7 @@ func Toggle(props ToggleProps) templ.Component { templ_7745c5c3_Var1 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 11) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/pkg/styles/goilerplate.css b/pkg/styles/goilerplate.css index 9b66f51..b3a187b 100644 --- a/pkg/styles/goilerplate.css +++ b/pkg/styles/goilerplate.css @@ -946,6 +946,15 @@ body { width: 100%; } +.w-fit { + width: -moz-fit-content; + width: fit-content; +} + +.min-w-\[14rem\] { + min-width: 14rem; +} + .max-w-md { max-width: 28rem; } @@ -1179,6 +1188,10 @@ body { border-radius: calc(var(--radius) - 4px); } +.rounded-none { + border-radius: 0px; +} + .border { border-width: 1px; } @@ -1187,6 +1200,10 @@ body { border-width: 2px; } +.border-4 { + border-width: 4px; +} + .border-b { border-bottom-width: 1px; } @@ -1313,6 +1330,16 @@ body { background-color: hsl(var(--secondary) / var(--tw-bg-opacity)); } +.bg-stone-200 { + --tw-bg-opacity: 1; + background-color: rgb(231 229 228 / var(--tw-bg-opacity)); +} + +.bg-stone-50 { + --tw-bg-opacity: 1; + background-color: rgb(250 250 249 / var(--tw-bg-opacity)); +} + .bg-opacity-50 { --tw-bg-opacity: 0.5; } @@ -1547,6 +1574,11 @@ body { color: hsl(var(--secondary-foreground) / var(--tw-text-opacity)); } +.text-stone-800 { + --tw-text-opacity: 1; + color: rgb(41 37 36 / var(--tw-text-opacity)); +} + .underline { text-decoration-line: underline; } @@ -1733,6 +1765,11 @@ body { color: hsl(var(--muted-foreground) / var(--tw-text-opacity)); } +.before\:invisible::before { + content: var(--tw-content); + visibility: hidden; +} + .before\:absolute::before { content: var(--tw-content); position: absolute; @@ -1743,6 +1780,71 @@ body { inset: 0px; } +.before\:left-1\/2::before { + content: var(--tw-content); + left: 50%; +} + +.before\:top-1\/2::before { + content: var(--tw-content); + top: 50%; +} + +.before\:h-1\.5::before { + content: var(--tw-content); + height: 0.375rem; +} + +.before\:h-2::before { + content: var(--tw-content); + height: 0.5rem; +} + +.before\:w-1\.5::before { + content: var(--tw-content); + width: 0.375rem; +} + +.before\:w-2::before { + content: var(--tw-content); + width: 0.5rem; +} + +.before\:-translate-x-1\/2::before { + content: var(--tw-content); + --tw-translate-x: -50%; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.before\:-translate-y-1\/2::before { + content: var(--tw-content); + --tw-translate-y: -50%; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.before\:rounded-full::before { + content: var(--tw-content); + border-radius: 9999px; +} + +.before\:bg-primary-foreground::before { + content: var(--tw-content); + --tw-bg-opacity: 1; + background-color: hsl(var(--primary-foreground) / var(--tw-bg-opacity)); +} + +.before\:bg-black::before { + content: var(--tw-content); + --tw-bg-opacity: 1; + background-color: rgb(0 0 0 / var(--tw-bg-opacity)); +} + +.before\:bg-background::before { + content: var(--tw-content); + --tw-bg-opacity: 1; + background-color: hsl(var(--background) / var(--tw-bg-opacity)); +} + .after\:absolute::after { content: var(--tw-content); position: absolute; @@ -1801,6 +1903,11 @@ body { background-color: hsl(var(--primary) / var(--tw-bg-opacity)); } +.checked\:bg-amber-500:checked { + --tw-bg-opacity: 1; + background-color: rgb(245 158 11 / var(--tw-bg-opacity)); +} + .checked\:outline-none:checked { outline: 2px solid transparent; outline-offset: 2px; @@ -1821,6 +1928,11 @@ body { --tw-ring-offset-width: 2px; } +.checked\:before\:visible:checked::before { + content: var(--tw-content); + visibility: visible; +} + .checked\:before\:bg-primary:checked::before { content: var(--tw-content); --tw-bg-opacity: 1; @@ -1917,6 +2029,10 @@ body { outline-color: hsl(var(--ring) / 1); } +.focus\:outline-blue-600:focus { + outline-color: #2563eb; +} + .focus\:ring-2:focus { --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color); --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color); @@ -1945,6 +2061,10 @@ body { outline-color: hsl(var(--primary) / 1); } +.checked\:focus\:outline-amber-500:focus:checked { + outline-color: #f59e0b; +} + .focus-visible\:outline-none:focus-visible { outline: 2px solid transparent; outline-offset: 2px; @@ -1965,6 +2085,10 @@ body { --tw-ring-offset-width: 2px; } +.focus-visible\:ring-offset-background:focus-visible { + --tw-ring-offset-color: hsl(var(--background) / 1); +} + .active\:outline-offset-0:active { outline-offset: 0px; } @@ -2033,21 +2157,59 @@ body { opacity: 0.5; } +.has-\[\:disabled\]\:opacity-75:has(:disabled) { + opacity: 0.75; +} + +.dark\:bg-stone-900:is(.dark *) { + --tw-bg-opacity: 1; + background-color: rgb(28 25 23 / var(--tw-bg-opacity)); +} + +.dark\:bg-stone-950:is(.dark *) { + --tw-bg-opacity: 1; + background-color: rgb(12 10 9 / var(--tw-bg-opacity)); +} + .dark\:text-gray-200:is(.dark *) { --tw-text-opacity: 1; color: rgb(229 231 235 / var(--tw-text-opacity)); } +.dark\:text-stone-300:is(.dark *) { + --tw-text-opacity: 1; + color: rgb(214 211 209 / var(--tw-text-opacity)); +} + .dark\:file\:text-foreground:is(.dark *)::file-selector-button { --tw-text-opacity: 1; color: hsl(var(--foreground) / var(--tw-text-opacity)); } +.dark\:before\:bg-black:is(.dark *)::before { + content: var(--tw-content); + --tw-bg-opacity: 1; + background-color: rgb(0 0 0 / var(--tw-bg-opacity)); +} + +.dark\:checked\:bg-amber-400:checked:is(.dark *) { + --tw-bg-opacity: 1; + background-color: rgb(251 191 36 / var(--tw-bg-opacity)); +} + .dark\:hover\:bg-gray-700:hover:is(.dark *) { --tw-bg-opacity: 1; background-color: rgb(55 65 81 / var(--tw-bg-opacity)); } +.dark\:focus\:outline-blue-500:focus:is(.dark *) { + outline-color: #3b82f6; +} + +.dark\:checked\:focus\:outline-amber-400:focus:checked:is(.dark *) { + outline-color: #fbbf24; +} + @media (min-width: 640px) { .sm\:my-8 { margin-top: 2rem; @@ -2113,6 +2275,14 @@ body { } } +.\[\&\:has\(\:disabled\)\]\:cursor-not-allowed:has(:disabled) { + cursor: not-allowed; +} + +.\[\&\:has\(\:disabled\)\]\:opacity-50:has(:disabled) { + opacity: 0.5; +} + .\[\&\:has\(input\:checked\)\]\:text-foreground:has(input:checked) { --tw-text-opacity: 1; color: hsl(var(--foreground) / var(--tw-text-opacity)); From cfe5a3e57baf7c0d5e4af53e4027f8f3725452f0 Mon Sep 17 00:00:00 2001 From: axzilla Date: Tue, 19 Nov 2024 16:25:25 +0700 Subject: [PATCH 05/17] change: simplify input component --- assets/css/output.css | 139 ------------------------------ internals/ui/pages/themes.templ | 6 +- internals/ui/showcase/input.templ | 2 +- internals/ui/showcase/tabs.templ | 8 +- pkg/components/input.templ | 36 +++----- pkg/components/input_templ.go | 77 +++++------------ pkg/styles/goilerplate.css | 135 +---------------------------- 7 files changed, 43 insertions(+), 360 deletions(-) diff --git a/assets/css/output.css b/assets/css/output.css index e332f32..c09c023 100644 --- a/assets/css/output.css +++ b/assets/css/output.css @@ -1010,15 +1010,6 @@ body { width: 100%; } -.w-fit { - width: -moz-fit-content; - width: fit-content; -} - -.min-w-\[14rem\] { - min-width: 14rem; -} - .max-w-3xl { max-width: 48rem; } @@ -1114,11 +1105,6 @@ body { transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); } -.translate-y-px { - --tw-translate-y: 1px; - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); -} - .scale-100 { --tw-scale-x: 1; --tw-scale-y: 1; @@ -1194,10 +1180,6 @@ body { grid-template-columns: repeat(7, minmax(0, 1fr)); } -.flex-row { - flex-direction: row; -} - .flex-col { flex-direction: column; } @@ -1349,10 +1331,6 @@ body { border-radius: calc(var(--radius) - 4px); } -.rounded-none { - border-radius: 0px; -} - .border { border-width: 1px; } @@ -1361,10 +1339,6 @@ body { border-width: 2px; } -.border-4 { - border-width: 4px; -} - .border-b { border-bottom-width: 1px; } @@ -1505,16 +1479,6 @@ body { background-color: rgb(255 255 255 / var(--tw-bg-opacity)); } -.bg-stone-200 { - --tw-bg-opacity: 1; - background-color: rgb(231 229 228 / var(--tw-bg-opacity)); -} - -.bg-stone-50 { - --tw-bg-opacity: 1; - background-color: rgb(250 250 249 / var(--tw-bg-opacity)); -} - .bg-opacity-50 { --tw-bg-opacity: 0.5; } @@ -1836,11 +1800,6 @@ body { color: rgb(255 255 255 / var(--tw-text-opacity)); } -.text-stone-800 { - --tw-text-opacity: 1; - color: rgb(41 37 36 / var(--tw-text-opacity)); -} - .underline { text-decoration-line: underline; } @@ -2031,11 +1990,6 @@ body { color: hsl(var(--muted-foreground) / var(--tw-text-opacity)); } -.before\:invisible::before { - content: var(--tw-content); - visibility: hidden; -} - .before\:absolute::before { content: var(--tw-content); position: absolute; @@ -2056,21 +2010,11 @@ body { top: 50%; } -.before\:h-1\.5::before { - content: var(--tw-content); - height: 0.375rem; -} - .before\:h-2::before { content: var(--tw-content); height: 0.5rem; } -.before\:w-1\.5::before { - content: var(--tw-content); - width: 0.375rem; -} - .before\:w-2::before { content: var(--tw-content); width: 0.5rem; @@ -2093,18 +2037,6 @@ body { border-radius: 9999px; } -.before\:bg-primary-foreground::before { - content: var(--tw-content); - --tw-bg-opacity: 1; - background-color: hsl(var(--primary-foreground) / var(--tw-bg-opacity)); -} - -.before\:bg-black::before { - content: var(--tw-content); - --tw-bg-opacity: 1; - background-color: rgb(0 0 0 / var(--tw-bg-opacity)); -} - .before\:bg-background::before { content: var(--tw-content); --tw-bg-opacity: 1; @@ -2169,31 +2101,6 @@ body { background-color: hsl(var(--primary) / var(--tw-bg-opacity)); } -.checked\:bg-amber-500:checked { - --tw-bg-opacity: 1; - background-color: rgb(245 158 11 / var(--tw-bg-opacity)); -} - -.checked\:outline-none:checked { - outline: 2px solid transparent; - outline-offset: 2px; -} - -.checked\:ring-2:checked { - --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color); - --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color); - box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000); -} - -.checked\:ring-ring:checked { - --tw-ring-opacity: 1; - --tw-ring-color: hsl(var(--ring) / var(--tw-ring-opacity)); -} - -.checked\:ring-offset-2:checked { - --tw-ring-offset-width: 2px; -} - .checked\:before\:visible:checked::before { content: var(--tw-content); visibility: visible; @@ -2314,10 +2221,6 @@ body { outline-color: hsl(var(--ring) / 1); } -.focus\:outline-blue-600:focus { - outline-color: #2563eb; -} - .focus\:ring-2:focus { --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color); --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color); @@ -2346,10 +2249,6 @@ body { outline-color: hsl(var(--primary) / 1); } -.checked\:focus\:outline-amber-500:focus:checked { - outline-color: #f59e0b; -} - .focus-visible\:outline-none:focus-visible { outline: 2px solid transparent; outline-offset: 2px; @@ -2452,20 +2351,6 @@ body { opacity: 0.7; } -.has-\[\:disabled\]\:opacity-75:has(:disabled) { - opacity: 0.75; -} - -.dark\:bg-stone-900:is(.dark *) { - --tw-bg-opacity: 1; - background-color: rgb(28 25 23 / var(--tw-bg-opacity)); -} - -.dark\:bg-stone-950:is(.dark *) { - --tw-bg-opacity: 1; - background-color: rgb(12 10 9 / var(--tw-bg-opacity)); -} - .dark\:from-gray-900:is(.dark *) { --tw-gradient-from: #111827 var(--tw-gradient-from-position); --tw-gradient-to: rgb(17 24 39 / 0) var(--tw-gradient-to-position); @@ -2496,40 +2381,16 @@ body { color: rgb(255 255 255 / var(--tw-text-opacity)); } -.dark\:text-stone-300:is(.dark *) { - --tw-text-opacity: 1; - color: rgb(214 211 209 / var(--tw-text-opacity)); -} - .dark\:file\:text-foreground:is(.dark *)::file-selector-button { --tw-text-opacity: 1; color: hsl(var(--foreground) / var(--tw-text-opacity)); } -.dark\:before\:bg-black:is(.dark *)::before { - content: var(--tw-content); - --tw-bg-opacity: 1; - background-color: rgb(0 0 0 / var(--tw-bg-opacity)); -} - -.dark\:checked\:bg-amber-400:checked:is(.dark *) { - --tw-bg-opacity: 1; - background-color: rgb(251 191 36 / var(--tw-bg-opacity)); -} - .dark\:hover\:bg-gray-700:hover:is(.dark *) { --tw-bg-opacity: 1; background-color: rgb(55 65 81 / var(--tw-bg-opacity)); } -.dark\:focus\:outline-blue-500:focus:is(.dark *) { - outline-color: #3b82f6; -} - -.dark\:checked\:focus\:outline-amber-400:focus:checked:is(.dark *) { - outline-color: #fbbf24; -} - @media (min-width: 640px) { .sm\:my-8 { margin-top: 2rem; diff --git a/internals/ui/pages/themes.templ b/internals/ui/pages/themes.templ index 04a6134..93775aa 100644 --- a/internals/ui/pages/themes.templ +++ b/internals/ui/pages/themes.templ @@ -70,7 +70,7 @@ templ ThemePreview() { @components.Input(components.InputProps{ ID: "username", Name: "username", - Type: components.Text, + Type: components.InputTypeText, Placeholder: "Enter your username", })
@@ -79,7 +79,7 @@ templ ThemePreview() { @components.Input(components.InputProps{ ID: "email", Name: "email", - Type: components.Email, + Type: components.InputTypeEmail, Placeholder: "Enter your email", })
@@ -88,7 +88,7 @@ templ ThemePreview() { @components.Input(components.InputProps{ ID: "password", Name: "password", - Type: components.Password, + Type: components.InputTypePassword, Placeholder: "Enter your password", })
diff --git a/internals/ui/showcase/input.templ b/internals/ui/showcase/input.templ index 2ec02c9..5a01155 100644 --- a/internals/ui/showcase/input.templ +++ b/internals/ui/showcase/input.templ @@ -25,7 +25,7 @@ templ InputShowcase() { @components.Input(components.InputProps{ Type: "email", Placeholder: "Email", - Disabled: "true", + Attributes: templ.Attributes{"disabled": "true"}, })
diff --git a/internals/ui/showcase/tabs.templ b/internals/ui/showcase/tabs.templ index 2d5168b..c0a33ed 100644 --- a/internals/ui/showcase/tabs.templ +++ b/internals/ui/showcase/tabs.templ @@ -38,7 +38,7 @@ templ AccountTab() {
@components.Input(components.InputProps{ - Type: components.Text, + Type: components.InputTypeText, Placeholder: "Name", ID: "name", Value: "John Doe", @@ -47,7 +47,7 @@ templ AccountTab() {
@components.Input(components.InputProps{ - Type: components.Text, + Type: components.InputTypeText, Placeholder: "Username", ID: "username", Value: "@johndoe", @@ -78,7 +78,7 @@ templ PasswordTab() { Current Password @components.Input(components.InputProps{ - Type: components.Password, + Type: components.InputTypePassword, Placeholder: "Current Password", ID: "current_password", }) @@ -88,7 +88,7 @@ templ PasswordTab() { New Password @components.Input(components.InputProps{ - Type: components.Password, + Type: components.InputTypePassword, Placeholder: "New Password", ID: "new_password", }) diff --git a/pkg/components/input.templ b/pkg/components/input.templ index 87eec93..60e0e22 100644 --- a/pkg/components/input.templ +++ b/pkg/components/input.templ @@ -7,16 +7,16 @@ type InputType string // Constants for input types. const ( - Text InputType = "text" - Password InputType = "password" - Email InputType = "email" - Number InputType = "number" - Tel InputType = "tel" - URL InputType = "url" - Search InputType = "search" - Date InputType = "date" - Time InputType = "time" - File InputType = "file" + InputTypeText InputType = "text" + InputTypePassword InputType = "password" + InputTypeEmail InputType = "email" + InputTypeNumber InputType = "number" + InputTypeTel InputType = "tel" + InputTypeURL InputType = "url" + InputTypeSearch InputType = "search" + InputTypeDate InputType = "date" + InputTypeTime InputType = "time" + InputTypeFile InputType = "file" ) // InputProps defines the properties for the Input component. @@ -45,12 +45,6 @@ type InputProps struct { // Default: "" (empty string) Class string - // Disabled can be either a bool or a string. - // If bool (Go), it directly controls the disabled state. - // If string, it's treated as a JavaScript expression for dynamic disabling. - // Default: nil - Disabled any - // FileAccept specifies which file types are accepted (only for file type). // Default: "" (empty string) FileAccept string @@ -100,15 +94,7 @@ templ Input(props InputProps) { "file:text-foreground dark:file:text-foreground", props.Class), } - if props.Disabled != nil { - if disabledBool, ok := props.Disabled.(bool); ok && disabledBool { - disabled="true" - } - if disabledStr, ok := props.Disabled.(string); ok { - :disabled={ disabledStr } - } - } - if props.Type == File { + if props.Type == InputTypeFile { accept={ props.FileAccept } } { props.Attributes... } diff --git a/pkg/components/input_templ.go b/pkg/components/input_templ.go index cc6a909..04b166a 100644 --- a/pkg/components/input_templ.go +++ b/pkg/components/input_templ.go @@ -15,16 +15,16 @@ type InputType string // Constants for input types. const ( - Text InputType = "text" - Password InputType = "password" - Email InputType = "email" - Number InputType = "number" - Tel InputType = "tel" - URL InputType = "url" - Search InputType = "search" - Date InputType = "date" - Time InputType = "time" - File InputType = "file" + InputTypeText InputType = "text" + InputTypePassword InputType = "password" + InputTypeEmail InputType = "email" + InputTypeNumber InputType = "number" + InputTypeTel InputType = "tel" + InputTypeURL InputType = "url" + InputTypeSearch InputType = "search" + InputTypeDate InputType = "date" + InputTypeTime InputType = "time" + InputTypeFile InputType = "file" ) // InputProps defines the properties for the Input component. @@ -53,12 +53,6 @@ type InputProps struct { // Default: "" (empty string) Class string - // Disabled can be either a bool or a string. - // If bool (Go), it directly controls the disabled state. - // If string, it's treated as a JavaScript expression for dynamic disabling. - // Default: nil - Disabled any - // FileAccept specifies which file types are accepted (only for file type). // Default: "" (empty string) FileAccept string @@ -134,7 +128,7 @@ func Input(props InputProps) templ.Component { var templ_7745c5c3_Var3 string templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(string(props.Type)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/components/input.templ`, Line: 91, Col: 27} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/components/input.templ`, Line: 85, Col: 27} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) if templ_7745c5c3_Err != nil { @@ -147,7 +141,7 @@ func Input(props InputProps) templ.Component { var templ_7745c5c3_Var4 string templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(props.Placeholder) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/components/input.templ`, Line: 92, Col: 33} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/components/input.templ`, Line: 86, Col: 33} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) if templ_7745c5c3_Err != nil { @@ -160,7 +154,7 @@ func Input(props InputProps) templ.Component { var templ_7745c5c3_Var5 string templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(props.Name) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/components/input.templ`, Line: 93, Col: 19} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/components/input.templ`, Line: 87, Col: 19} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) if templ_7745c5c3_Err != nil { @@ -173,7 +167,7 @@ func Input(props InputProps) templ.Component { var templ_7745c5c3_Var6 string templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(props.ID) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/components/input.templ`, Line: 94, Col: 15} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/components/input.templ`, Line: 88, Col: 15} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) if templ_7745c5c3_Err != nil { @@ -196,48 +190,21 @@ func Input(props InputProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - if props.Disabled != nil { - if disabledBool, ok := props.Disabled.(bool); ok && disabledBool { - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 7) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } - if disabledStr, ok := props.Disabled.(string); ok { - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 8) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var8 string - templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(disabledStr) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/components/input.templ`, Line: 108, Col: 27} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 9) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } - } - if props.Type == File { - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 10) + if props.Type == InputTypeFile { + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 7) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var9 string - templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(props.FileAccept) + var templ_7745c5c3_Var8 string + templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(props.FileAccept) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/components/input.templ`, Line: 112, Col: 28} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/components/input.templ`, Line: 98, Col: 28} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 11) + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 8) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -246,7 +213,7 @@ func Input(props InputProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 12) + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 9) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/pkg/styles/goilerplate.css b/pkg/styles/goilerplate.css index b3a187b..6182343 100644 --- a/pkg/styles/goilerplate.css +++ b/pkg/styles/goilerplate.css @@ -946,15 +946,6 @@ body { width: 100%; } -.w-fit { - width: -moz-fit-content; - width: fit-content; -} - -.min-w-\[14rem\] { - min-width: 14rem; -} - .max-w-md { max-width: 28rem; } @@ -1011,11 +1002,6 @@ body { transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); } -.translate-y-px { - --tw-translate-y: 1px; - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); -} - .scale-100 { --tw-scale-x: 1; --tw-scale-y: 1; @@ -1188,10 +1174,6 @@ body { border-radius: calc(var(--radius) - 4px); } -.rounded-none { - border-radius: 0px; -} - .border { border-width: 1px; } @@ -1200,10 +1182,6 @@ body { border-width: 2px; } -.border-4 { - border-width: 4px; -} - .border-b { border-bottom-width: 1px; } @@ -1330,16 +1308,6 @@ body { background-color: hsl(var(--secondary) / var(--tw-bg-opacity)); } -.bg-stone-200 { - --tw-bg-opacity: 1; - background-color: rgb(231 229 228 / var(--tw-bg-opacity)); -} - -.bg-stone-50 { - --tw-bg-opacity: 1; - background-color: rgb(250 250 249 / var(--tw-bg-opacity)); -} - .bg-opacity-50 { --tw-bg-opacity: 0.5; } @@ -1574,11 +1542,6 @@ body { color: hsl(var(--secondary-foreground) / var(--tw-text-opacity)); } -.text-stone-800 { - --tw-text-opacity: 1; - color: rgb(41 37 36 / var(--tw-text-opacity)); -} - .underline { text-decoration-line: underline; } @@ -1765,11 +1728,6 @@ body { color: hsl(var(--muted-foreground) / var(--tw-text-opacity)); } -.before\:invisible::before { - content: var(--tw-content); - visibility: hidden; -} - .before\:absolute::before { content: var(--tw-content); position: absolute; @@ -1790,21 +1748,11 @@ body { top: 50%; } -.before\:h-1\.5::before { - content: var(--tw-content); - height: 0.375rem; -} - .before\:h-2::before { content: var(--tw-content); height: 0.5rem; } -.before\:w-1\.5::before { - content: var(--tw-content); - width: 0.375rem; -} - .before\:w-2::before { content: var(--tw-content); width: 0.5rem; @@ -1827,18 +1775,6 @@ body { border-radius: 9999px; } -.before\:bg-primary-foreground::before { - content: var(--tw-content); - --tw-bg-opacity: 1; - background-color: hsl(var(--primary-foreground) / var(--tw-bg-opacity)); -} - -.before\:bg-black::before { - content: var(--tw-content); - --tw-bg-opacity: 1; - background-color: rgb(0 0 0 / var(--tw-bg-opacity)); -} - .before\:bg-background::before { content: var(--tw-content); --tw-bg-opacity: 1; @@ -1903,31 +1839,6 @@ body { background-color: hsl(var(--primary) / var(--tw-bg-opacity)); } -.checked\:bg-amber-500:checked { - --tw-bg-opacity: 1; - background-color: rgb(245 158 11 / var(--tw-bg-opacity)); -} - -.checked\:outline-none:checked { - outline: 2px solid transparent; - outline-offset: 2px; -} - -.checked\:ring-2:checked { - --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color); - --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color); - box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000); -} - -.checked\:ring-ring:checked { - --tw-ring-opacity: 1; - --tw-ring-color: hsl(var(--ring) / var(--tw-ring-opacity)); -} - -.checked\:ring-offset-2:checked { - --tw-ring-offset-width: 2px; -} - .checked\:before\:visible:checked::before { content: var(--tw-content); visibility: visible; @@ -2029,10 +1940,6 @@ body { outline-color: hsl(var(--ring) / 1); } -.focus\:outline-blue-600:focus { - outline-color: #2563eb; -} - .focus\:ring-2:focus { --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color); --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color); @@ -2061,10 +1968,6 @@ body { outline-color: hsl(var(--primary) / 1); } -.checked\:focus\:outline-amber-500:focus:checked { - outline-color: #f59e0b; -} - .focus-visible\:outline-none:focus-visible { outline: 2px solid transparent; outline-offset: 2px; @@ -2157,18 +2060,8 @@ body { opacity: 0.5; } -.has-\[\:disabled\]\:opacity-75:has(:disabled) { - opacity: 0.75; -} - -.dark\:bg-stone-900:is(.dark *) { - --tw-bg-opacity: 1; - background-color: rgb(28 25 23 / var(--tw-bg-opacity)); -} - -.dark\:bg-stone-950:is(.dark *) { - --tw-bg-opacity: 1; - background-color: rgb(12 10 9 / var(--tw-bg-opacity)); +.peer:disabled ~ .peer-disabled\:opacity-70 { + opacity: 0.7; } .dark\:text-gray-200:is(.dark *) { @@ -2176,40 +2069,16 @@ body { color: rgb(229 231 235 / var(--tw-text-opacity)); } -.dark\:text-stone-300:is(.dark *) { - --tw-text-opacity: 1; - color: rgb(214 211 209 / var(--tw-text-opacity)); -} - .dark\:file\:text-foreground:is(.dark *)::file-selector-button { --tw-text-opacity: 1; color: hsl(var(--foreground) / var(--tw-text-opacity)); } -.dark\:before\:bg-black:is(.dark *)::before { - content: var(--tw-content); - --tw-bg-opacity: 1; - background-color: rgb(0 0 0 / var(--tw-bg-opacity)); -} - -.dark\:checked\:bg-amber-400:checked:is(.dark *) { - --tw-bg-opacity: 1; - background-color: rgb(251 191 36 / var(--tw-bg-opacity)); -} - .dark\:hover\:bg-gray-700:hover:is(.dark *) { --tw-bg-opacity: 1; background-color: rgb(55 65 81 / var(--tw-bg-opacity)); } -.dark\:focus\:outline-blue-500:focus:is(.dark *) { - outline-color: #3b82f6; -} - -.dark\:checked\:focus\:outline-amber-400:focus:checked:is(.dark *) { - outline-color: #fbbf24; -} - @media (min-width: 640px) { .sm\:my-8 { margin-top: 2rem; From c1fb04f0f882f14be4fe6e21705fd23b6ddc54e3 Mon Sep 17 00:00:00 2001 From: axzilla Date: Tue, 19 Nov 2024 16:31:13 +0700 Subject: [PATCH 06/17] hotfix: remove dev component code --- pkg/components/accordion_templ.go | 20 ++++---- pkg/components/alert_templ.go | 14 +++--- pkg/components/avatar_templ.go | 18 +++---- pkg/components/button_templ.go | 42 ++++++++-------- pkg/components/card_templ.go | 28 +++++------ pkg/components/checkbox.templ | 2 +- pkg/components/checkbox_templ.go | 22 ++++----- pkg/components/datepicker_templ.go | 20 ++++---- pkg/components/dropdown_menu_templ.go | 70 +++++++++++++-------------- pkg/components/footer_templ.go | 4 +- pkg/components/form_templ.go | 16 +++--- pkg/components/input_templ.go | 18 +++---- pkg/components/modal_templ.go | 34 ++++++------- pkg/components/navbar_templ.go | 28 +++++------ pkg/components/radio_group_templ.go | 28 +++++------ pkg/components/select_templ.go | 62 ++++++++++++------------ pkg/components/sheet_templ.go | 38 +++++++-------- pkg/components/sidebar_right_templ.go | 18 +++---- pkg/components/sidebar_templ.go | 16 +++--- pkg/components/tabs_templ.go | 22 ++++----- pkg/components/themeswitcher_templ.go | 6 +-- pkg/components/toggle_templ.go | 22 ++++----- 22 files changed, 274 insertions(+), 274 deletions(-) diff --git a/pkg/components/accordion_templ.go b/pkg/components/accordion_templ.go index f549345..922647c 100644 --- a/pkg/components/accordion_templ.go +++ b/pkg/components/accordion_templ.go @@ -94,7 +94,7 @@ func Accordion(props AccordionProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 1) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } for _, item := range props.Items { - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 4) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -179,12 +179,12 @@ func Accordion(props AccordionProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 9) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 10) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/pkg/components/alert_templ.go b/pkg/components/alert_templ.go index 89dc2da..198bafe 100644 --- a/pkg/components/alert_templ.go +++ b/pkg/components/alert_templ.go @@ -86,7 +86,7 @@ func Alert(props AlertProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 1) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -107,7 +107,7 @@ func Alert(props AlertProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 3) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -137,7 +137,7 @@ func AlertTitle() templ.Component { templ_7745c5c3_Var4 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 4) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -145,7 +145,7 @@ func AlertTitle() templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 5) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -175,7 +175,7 @@ func AlertDescription() templ.Component { templ_7745c5c3_Var5 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 6) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -183,7 +183,7 @@ func AlertDescription() templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 7) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/pkg/components/avatar_templ.go b/pkg/components/avatar_templ.go index 459ecc2..6b72e11 100644 --- a/pkg/components/avatar_templ.go +++ b/pkg/components/avatar_templ.go @@ -120,7 +120,7 @@ func Avatar(props AvatarProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 1) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if props.ImageSrc != "" { - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 4) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"")") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } else { - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 7) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -190,12 +190,12 @@ func Avatar(props AvatarProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 8) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 9) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/pkg/components/button_templ.go b/pkg/components/button_templ.go index 1419f76..078b233 100644 --- a/pkg/components/button_templ.go +++ b/pkg/components/button_templ.go @@ -193,7 +193,7 @@ func Button(props ButtonProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 1) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -275,7 +275,7 @@ func Button(props ButtonProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 9) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -295,7 +295,7 @@ func Button(props ButtonProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 10) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -407,7 +407,7 @@ func renderButtonContent(props ButtonProps) templ.Component { templ_7745c5c3_Var11 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 19) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -426,7 +426,7 @@ func renderButtonContent(props ButtonProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 20) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -436,7 +436,7 @@ func renderButtonContent(props ButtonProps) templ.Component { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 21) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/pkg/components/card_templ.go b/pkg/components/card_templ.go index 3ed747a..72f4ffb 100644 --- a/pkg/components/card_templ.go +++ b/pkg/components/card_templ.go @@ -62,7 +62,7 @@ func Card(props CardProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 1) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -91,7 +91,7 @@ func Card(props CardProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 4) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -128,7 +128,7 @@ func CardHeader() templ.Component { templ_7745c5c3_Var4 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 5) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -136,7 +136,7 @@ func CardHeader() templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 6) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -172,7 +172,7 @@ func CardTitle() templ.Component { templ_7745c5c3_Var5 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 7) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -180,7 +180,7 @@ func CardTitle() templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 8) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -216,7 +216,7 @@ func CardDescription() templ.Component { templ_7745c5c3_Var6 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 9) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -224,7 +224,7 @@ func CardDescription() templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 10) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -260,7 +260,7 @@ func CardContent() templ.Component { templ_7745c5c3_Var7 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 11) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -268,7 +268,7 @@ func CardContent() templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 12) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -304,7 +304,7 @@ func CardFooter() templ.Component { templ_7745c5c3_Var8 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 13) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -312,7 +312,7 @@ func CardFooter() templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 14) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/pkg/components/checkbox.templ b/pkg/components/checkbox.templ index d30180a..2ada1f4 100644 --- a/pkg/components/checkbox.templ +++ b/pkg/components/checkbox.templ @@ -52,7 +52,7 @@ templ Checkbox(props CheckboxProps) { value={ props.Value } type="checkbox" class="before:content[''] peer relative size-4 cursor-pointer appearance-none overflow-hidden - rounded-sm border border-primary + rounded-sm border border-2 border-primary bg-background before:absolute before:inset-0 checked:before:bg-primary focus:outline focus:outline-2 focus:outline-offset-2 diff --git a/pkg/components/checkbox_templ.go b/pkg/components/checkbox_templ.go index 37a49dd..868546e 100644 --- a/pkg/components/checkbox_templ.go +++ b/pkg/components/checkbox_templ.go @@ -75,7 +75,7 @@ func Checkbox(props CheckboxProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 1) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/pkg/components/datepicker_templ.go b/pkg/components/datepicker_templ.go index 199c39f..8eaafda 100644 --- a/pkg/components/datepicker_templ.go +++ b/pkg/components/datepicker_templ.go @@ -82,7 +82,7 @@ func Datepicker(props DatepickerProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 1) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -163,7 +163,7 @@ func Datepicker(props DatepickerProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 8) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/pkg/components/dropdown_menu_templ.go b/pkg/components/dropdown_menu_templ.go index d76ea5f..91f3fff 100644 --- a/pkg/components/dropdown_menu_templ.go +++ b/pkg/components/dropdown_menu_templ.go @@ -72,7 +72,7 @@ func renderMenuItem(item DropdownMenuItem, index int, depth int) templ.Component } ctx = templ.ClearChildren(ctx) if len(item.SubItems) > 0 { - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 1) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -86,7 +86,7 @@ func renderMenuItem(item DropdownMenuItem, index int, depth int) templ.Component if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 2) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if depth < 3 { - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 9) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 11) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -194,7 +194,7 @@ func renderMenuItem(item DropdownMenuItem, index int, depth int) templ.Component if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 12) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -269,12 +269,12 @@ func renderMenuItem(item DropdownMenuItem, index int, depth int) templ.Component if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 18) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if item.IconRight != nil { - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 19) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -282,12 +282,12 @@ func renderMenuItem(item DropdownMenuItem, index int, depth int) templ.Component if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 20) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 21) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -301,7 +301,7 @@ func renderMenuItem(item DropdownMenuItem, index int, depth int) templ.Component if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 22) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -440,7 +440,7 @@ func DropdownMenu(props DropdownMenuProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 29) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -485,7 +485,7 @@ func DropdownMenu(props DropdownMenuProps) templ.Component { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 32) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -497,7 +497,7 @@ func DropdownMenu(props DropdownMenuProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 33) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -520,7 +520,7 @@ func DropdownMenu(props DropdownMenuProps) templ.Component { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 35) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/pkg/components/footer_templ.go b/pkg/components/footer_templ.go index 32fc075..e4841e9 100644 --- a/pkg/components/footer_templ.go +++ b/pkg/components/footer_templ.go @@ -32,7 +32,7 @@ func Footer() templ.Component { templ_7745c5c3_Var1 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 1) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -45,7 +45,7 @@ func Footer() templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 2) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" Stupid code not excluded.

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/pkg/components/form_templ.go b/pkg/components/form_templ.go index 26db1ab..27df1c9 100644 --- a/pkg/components/form_templ.go +++ b/pkg/components/form_templ.go @@ -64,7 +64,7 @@ func Form[T FormDataProvider](props FormProps[T]) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 1) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -143,7 +143,7 @@ func Form[T FormDataProvider](props FormProps[T]) templ.Component { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 7) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -173,7 +173,7 @@ func FormDebug() templ.Component { templ_7745c5c3_Var7 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 8) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("

Form Debug

Form Data:

Errors:

State:

Submitting:
Submitted:
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/pkg/components/input_templ.go b/pkg/components/input_templ.go index 04b166a..fb8d261 100644 --- a/pkg/components/input_templ.go +++ b/pkg/components/input_templ.go @@ -121,7 +121,7 @@ func Input(props InputProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 1) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/pkg/components/modal_templ.go b/pkg/components/modal_templ.go index 3d04ab2..8700b11 100644 --- a/pkg/components/modal_templ.go +++ b/pkg/components/modal_templ.go @@ -76,7 +76,7 @@ func Modal(props ModalProps) templ.Component { templ_7745c5c3_Var1 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 1) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -102,7 +102,7 @@ func Modal(props ModalProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 3) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -123,7 +123,7 @@ func Modal(props ModalProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 5) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -161,7 +161,7 @@ func ModalTrigger(id string) templ.Component { templ_7745c5c3_Var5 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 6) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -182,7 +182,7 @@ func ModalTrigger(id string) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 8) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -223,7 +223,7 @@ func ModalClose(id string) templ.Component { templ_7745c5c3_Var7 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 9) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -244,7 +244,7 @@ func ModalClose(id string) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 11) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -281,7 +281,7 @@ func ModalHeader() templ.Component { templ_7745c5c3_Var9 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 12) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -289,7 +289,7 @@ func ModalHeader() templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 13) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -325,7 +325,7 @@ func ModalBody() templ.Component { templ_7745c5c3_Var10 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 14) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -333,7 +333,7 @@ func ModalBody() templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 15) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -374,7 +374,7 @@ func ModalFooter() templ.Component { templ_7745c5c3_Var11 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 16) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -382,7 +382,7 @@ func ModalFooter() templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 17) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/pkg/components/navbar_templ.go b/pkg/components/navbar_templ.go index 79c0e3f..1f34cbe 100644 --- a/pkg/components/navbar_templ.go +++ b/pkg/components/navbar_templ.go @@ -34,7 +34,7 @@ func Navbar() templ.Component { templ_7745c5c3_Var1 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 1) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -112,7 +112,7 @@ func NavbarMobileMenu() templ.Component { } ctx = templ.InitializeContext(ctx) for _, section := range shared.Sections { - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 4) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -125,12 +125,12 @@ func NavbarMobileMenu() templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 5) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -191,7 +191,7 @@ func NavbarMobileMenu() templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 12) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -207,7 +207,7 @@ func NavbarMobileMenu() templ.Component { }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 13) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/pkg/components/radio_group_templ.go b/pkg/components/radio_group_templ.go index 9ddaaae..f1b3208 100644 --- a/pkg/components/radio_group_templ.go +++ b/pkg/components/radio_group_templ.go @@ -76,7 +76,7 @@ func RadioGroup(props RadioGroupProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 1) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -105,7 +105,7 @@ func RadioGroup(props RadioGroupProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 4) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -154,7 +154,7 @@ func RadioGroupItem(props RadioGroupItemProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 5) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/pkg/components/select_templ.go b/pkg/components/select_templ.go index 874e91f..79e614d 100644 --- a/pkg/components/select_templ.go +++ b/pkg/components/select_templ.go @@ -109,7 +109,7 @@ func Select(props SelectProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 1) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -294,7 +294,7 @@ func Select(props SelectProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 19) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -353,7 +353,7 @@ func Select(props SelectProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 25) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
  • ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -392,7 +392,7 @@ func Select(props SelectProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 28) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -413,12 +413,12 @@ func Select(props SelectProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 30) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
  • ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 31) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/pkg/components/sheet_templ.go b/pkg/components/sheet_templ.go index bcf5a04..c9885b9 100644 --- a/pkg/components/sheet_templ.go +++ b/pkg/components/sheet_templ.go @@ -62,7 +62,7 @@ func SheetRoot() templ.Component { templ_7745c5c3_Var1 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 1) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -70,7 +70,7 @@ func SheetRoot() templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 2) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -115,35 +115,35 @@ func Sheet(props SheetProps) templ.Component { templ_7745c5c3_Var2 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 3) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -156,7 +156,7 @@ func Sheet(props SheetProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 9) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -182,7 +182,7 @@ func Sheet(props SheetProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 11) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -195,7 +195,7 @@ func Sheet(props SheetProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 12) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -203,7 +203,7 @@ func Sheet(props SheetProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 13) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -243,7 +243,7 @@ func SheetTrigger(text string, side SheetSide) templ.Component { templ_7745c5c3_Var7 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 14) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -264,7 +264,7 @@ func SheetTrigger(text string, side SheetSide) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 16) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -309,7 +309,7 @@ func SheetClose(text string) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 17) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/pkg/components/sidebar_right_templ.go b/pkg/components/sidebar_right_templ.go index a9528ed..d98e40f 100644 --- a/pkg/components/sidebar_right_templ.go +++ b/pkg/components/sidebar_right_templ.go @@ -55,12 +55,12 @@ func SidebarRight() templ.Component { templ_7745c5c3_Var1 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 1) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/pkg/components/sidebar_templ.go b/pkg/components/sidebar_templ.go index 455248c..23584a0 100644 --- a/pkg/components/sidebar_templ.go +++ b/pkg/components/sidebar_templ.go @@ -31,12 +31,12 @@ func Sidebar() templ.Component { templ_7745c5c3_Var1 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 1) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/pkg/components/tabs_templ.go b/pkg/components/tabs_templ.go index 9a27594..0a1dce4 100644 --- a/pkg/components/tabs_templ.go +++ b/pkg/components/tabs_templ.go @@ -73,7 +73,7 @@ func Tabs(props TabsProps) templ.Component { templ_7745c5c3_Var1 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 1) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -84,7 +84,7 @@ func Tabs(props TabsProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 2) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } for _, tab := range props.Tabs { - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 4) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 6) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -129,7 +129,7 @@ func Tabs(props TabsProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 7) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } for _, tab := range props.Tabs { - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 9) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -155,12 +155,12 @@ func Tabs(props TabsProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 10) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 11) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/pkg/components/themeswitcher_templ.go b/pkg/components/themeswitcher_templ.go index 972fe45..e57fd17 100644 --- a/pkg/components/themeswitcher_templ.go +++ b/pkg/components/themeswitcher_templ.go @@ -67,7 +67,7 @@ func DynamicThemeIcon() templ.Component { templ_7745c5c3_Var2 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 1) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -75,7 +75,7 @@ func DynamicThemeIcon() templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 2) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -83,7 +83,7 @@ func DynamicThemeIcon() templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 3) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/pkg/components/toggle_templ.go b/pkg/components/toggle_templ.go index bdcbbda..d24c9cd 100644 --- a/pkg/components/toggle_templ.go +++ b/pkg/components/toggle_templ.go @@ -67,7 +67,7 @@ func Toggle(props ToggleProps) templ.Component { templ_7745c5c3_Var1 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 1) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } From b0bb342a6897d83078727e6b4924ef4b232802c8 Mon Sep 17 00:00:00 2001 From: axzilla Date: Tue, 19 Nov 2024 17:34:59 +0700 Subject: [PATCH 07/17] hotfix: remove redundant code a base layout --- internals/ui/layouts/base.templ | 1 - 1 file changed, 1 deletion(-) diff --git a/internals/ui/layouts/base.templ b/internals/ui/layouts/base.templ index 441fed1..9c17301 100644 --- a/internals/ui/layouts/base.templ +++ b/internals/ui/layouts/base.templ @@ -60,7 +60,6 @@ templ BaseLayout() { class="h-full flex flex-col transition-colors duration-200" :class="{'bg-white text-black': appTheme === 'light', 'text-white': appTheme === 'dark'}" > -
Loading...
{ children... }
From 577e22651b6ef5590d4165d9498156a92552125a Mon Sep 17 00:00:00 2001 From: axzilla Date: Tue, 19 Nov 2024 17:36:00 +0700 Subject: [PATCH 08/17] change: make datepicker work with external x-model to use it with form component --- assets/css/output.css | 76 +++++++++++++++++++++++++ pkg/components/datepicker.templ | 2 +- pkg/components/datepicker_templ.go | 2 +- pkg/styles/goilerplate.css | 91 +++++++++++++++++++++++++++++- 4 files changed, 167 insertions(+), 4 deletions(-) diff --git a/assets/css/output.css b/assets/css/output.css index c09c023..33f509a 100644 --- a/assets/css/output.css +++ b/assets/css/output.css @@ -735,6 +735,10 @@ body { top: 100%; } +.start-0 { + inset-inline-start: 0px; +} + .z-10 { z-index: 10; } @@ -1389,6 +1393,11 @@ body { border-color: transparent; } +.border-gray-300 { + --tw-border-opacity: 1; + border-color: rgb(209 213 219 / var(--tw-border-opacity)); +} + .bg-\[--theme-primary\] { background-color: var(--theme-primary); } @@ -1479,6 +1488,11 @@ body { background-color: rgb(255 255 255 / var(--tw-bg-opacity)); } +.bg-gray-50 { + --tw-bg-opacity: 1; + background-color: rgb(249 250 251 / var(--tw-bg-opacity)); +} + .bg-opacity-50 { --tw-bg-opacity: 0.5; } @@ -1523,6 +1537,10 @@ body { padding: 1.5rem; } +.p-2\.5 { + padding: 0.625rem; +} + .px-0\.5 { padding-left: 0.125rem; padding-right: 0.125rem; @@ -1598,6 +1616,11 @@ body { padding-bottom: 2rem; } +.px-0 { + padding-left: 0px; + padding-right: 0px; +} + .pb-4 { padding-bottom: 1rem; } @@ -1626,6 +1649,14 @@ body { padding-top: 1.25rem; } +.ps-10 { + padding-inline-start: 2.5rem; +} + +.ps-3\.5 { + padding-inline-start: 0.875rem; +} + .text-left { text-align: left; } @@ -1800,6 +1831,11 @@ body { color: rgb(255 255 255 / var(--tw-text-opacity)); } +.text-gray-500 { + --tw-text-opacity: 1; + color: rgb(107 114 128 / var(--tw-text-opacity)); +} + .underline { text-decoration-line: underline; } @@ -2190,6 +2226,11 @@ body { opacity: 0.8; } +.focus\:border-blue-500:focus { + --tw-border-opacity: 1; + border-color: rgb(59 130 246 / var(--tw-border-opacity)); +} + .focus\:bg-accent:focus { --tw-bg-opacity: 1; background-color: hsl(var(--accent) / var(--tw-bg-opacity)); @@ -2241,6 +2282,11 @@ body { --tw-ring-color: hsl(var(--ring) / var(--tw-ring-opacity)); } +.focus\:ring-blue-500:focus { + --tw-ring-opacity: 1; + --tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity)); +} + .focus\:ring-offset-2:focus { --tw-ring-offset-width: 2px; } @@ -2351,6 +2397,16 @@ body { opacity: 0.7; } +.dark\:border-gray-600:is(.dark *) { + --tw-border-opacity: 1; + border-color: rgb(75 85 99 / var(--tw-border-opacity)); +} + +.dark\:bg-gray-700:is(.dark *) { + --tw-bg-opacity: 1; + background-color: rgb(55 65 81 / var(--tw-bg-opacity)); +} + .dark\:from-gray-900:is(.dark *) { --tw-gradient-from: #111827 var(--tw-gradient-from-position); --tw-gradient-to: rgb(17 24 39 / 0) var(--tw-gradient-to-position); @@ -2381,6 +2437,16 @@ body { color: rgb(255 255 255 / var(--tw-text-opacity)); } +.dark\:placeholder-gray-400:is(.dark *)::-moz-placeholder { + --tw-placeholder-opacity: 1; + color: rgb(156 163 175 / var(--tw-placeholder-opacity)); +} + +.dark\:placeholder-gray-400:is(.dark *)::placeholder { + --tw-placeholder-opacity: 1; + color: rgb(156 163 175 / var(--tw-placeholder-opacity)); +} + .dark\:file\:text-foreground:is(.dark *)::file-selector-button { --tw-text-opacity: 1; color: hsl(var(--foreground) / var(--tw-text-opacity)); @@ -2391,6 +2457,16 @@ body { background-color: rgb(55 65 81 / var(--tw-bg-opacity)); } +.dark\:focus\:border-blue-500:focus:is(.dark *) { + --tw-border-opacity: 1; + border-color: rgb(59 130 246 / var(--tw-border-opacity)); +} + +.dark\:focus\:ring-blue-500:focus:is(.dark *) { + --tw-ring-opacity: 1; + --tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity)); +} + @media (min-width: 640px) { .sm\:my-8 { margin-top: 2rem; diff --git a/pkg/components/datepicker.templ b/pkg/components/datepicker.templ index b8f9bac..d79bf89 100644 --- a/pkg/components/datepicker.templ +++ b/pkg/components/datepicker.templ @@ -174,7 +174,7 @@ templ Datepicker(props DatepickerProps) { id={ props.ID } name={ props.Name } placeholder={ props.Placeholder } - x-model="datePickerValue" + x-modelable="datePickerValue" @click="toggleDatePicker()" x-on:keydown.escape="datePickerOpen = false" x-ref="datePickerInput" diff --git a/pkg/components/datepicker_templ.go b/pkg/components/datepicker_templ.go index 8eaafda..9fface7 100644 --- a/pkg/components/datepicker_templ.go +++ b/pkg/components/datepicker_templ.go @@ -147,7 +147,7 @@ func Datepicker(props DatepickerProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" x-model=\"datePickerValue\" @click=\"toggleDatePicker()\" x-on:keydown.escape=\"datePickerOpen = false\" x-ref=\"datePickerInput\" class=\"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50\" readonly") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" x-modelable=\"datePickerValue\" @click=\"toggleDatePicker()\" x-on:keydown.escape=\"datePickerOpen = false\" x-ref=\"datePickerInput\" class=\"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50\" readonly") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/pkg/styles/goilerplate.css b/pkg/styles/goilerplate.css index 6182343..beca0ec 100644 --- a/pkg/styles/goilerplate.css +++ b/pkg/styles/goilerplate.css @@ -731,6 +731,10 @@ body { top: 100%; } +.start-0 { + inset-inline-start: 0px; +} + .z-10 { z-index: 10; } @@ -1232,6 +1236,11 @@ body { border-color: transparent; } +.border-gray-300 { + --tw-border-opacity: 1; + border-color: rgb(209 213 219 / var(--tw-border-opacity)); +} + .bg-accent { --tw-bg-opacity: 1; background-color: hsl(var(--accent) / var(--tw-bg-opacity)); @@ -1308,6 +1317,11 @@ body { background-color: hsl(var(--secondary) / var(--tw-bg-opacity)); } +.bg-gray-50 { + --tw-bg-opacity: 1; + background-color: rgb(249 250 251 / var(--tw-bg-opacity)); +} + .bg-opacity-50 { --tw-bg-opacity: 0.5; } @@ -1333,6 +1347,10 @@ body { padding: 1.5rem; } +.p-2\.5 { + padding: 0.625rem; +} + .px-0\.5 { padding-left: 0.125rem; padding-right: 0.125rem; @@ -1388,6 +1406,11 @@ body { padding-bottom: 1.5rem; } +.px-0 { + padding-left: 0px; + padding-right: 0px; +} + .pb-4 { padding-bottom: 1rem; } @@ -1408,6 +1431,14 @@ body { padding-top: 1.25rem; } +.ps-10 { + padding-inline-start: 2.5rem; +} + +.ps-3\.5 { + padding-inline-start: 0.875rem; +} + .text-left { text-align: left; } @@ -1542,6 +1573,16 @@ body { color: hsl(var(--secondary-foreground) / var(--tw-text-opacity)); } +.text-gray-500 { + --tw-text-opacity: 1; + color: rgb(107 114 128 / var(--tw-text-opacity)); +} + +.text-gray-900 { + --tw-text-opacity: 1; + color: rgb(17 24 39 / var(--tw-text-opacity)); +} + .underline { text-decoration-line: underline; } @@ -1909,6 +1950,11 @@ body { opacity: 1; } +.focus\:border-blue-500:focus { + --tw-border-opacity: 1; + border-color: rgb(59 130 246 / var(--tw-border-opacity)); +} + .focus\:bg-accent:focus { --tw-bg-opacity: 1; background-color: hsl(var(--accent) / var(--tw-bg-opacity)); @@ -1960,6 +2006,11 @@ body { --tw-ring-color: hsl(var(--ring) / var(--tw-ring-opacity)); } +.focus\:ring-blue-500:focus { + --tw-ring-opacity: 1; + --tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity)); +} + .focus\:ring-offset-2:focus { --tw-ring-offset-width: 2px; } @@ -2060,8 +2111,14 @@ body { opacity: 0.5; } -.peer:disabled ~ .peer-disabled\:opacity-70 { - opacity: 0.7; +.dark\:border-gray-600:is(.dark *) { + --tw-border-opacity: 1; + border-color: rgb(75 85 99 / var(--tw-border-opacity)); +} + +.dark\:bg-gray-700:is(.dark *) { + --tw-bg-opacity: 1; + background-color: rgb(55 65 81 / var(--tw-bg-opacity)); } .dark\:text-gray-200:is(.dark *) { @@ -2069,6 +2126,26 @@ body { color: rgb(229 231 235 / var(--tw-text-opacity)); } +.dark\:text-gray-400:is(.dark *) { + --tw-text-opacity: 1; + color: rgb(156 163 175 / var(--tw-text-opacity)); +} + +.dark\:text-white:is(.dark *) { + --tw-text-opacity: 1; + color: rgb(255 255 255 / var(--tw-text-opacity)); +} + +.dark\:placeholder-gray-400:is(.dark *)::-moz-placeholder { + --tw-placeholder-opacity: 1; + color: rgb(156 163 175 / var(--tw-placeholder-opacity)); +} + +.dark\:placeholder-gray-400:is(.dark *)::placeholder { + --tw-placeholder-opacity: 1; + color: rgb(156 163 175 / var(--tw-placeholder-opacity)); +} + .dark\:file\:text-foreground:is(.dark *)::file-selector-button { --tw-text-opacity: 1; color: hsl(var(--foreground) / var(--tw-text-opacity)); @@ -2079,6 +2156,16 @@ body { background-color: rgb(55 65 81 / var(--tw-bg-opacity)); } +.dark\:focus\:border-blue-500:focus:is(.dark *) { + --tw-border-opacity: 1; + border-color: rgb(59 130 246 / var(--tw-border-opacity)); +} + +.dark\:focus\:ring-blue-500:focus:is(.dark *) { + --tw-ring-opacity: 1; + --tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity)); +} + @media (min-width: 640px) { .sm\:my-8 { margin-top: 2rem; From 0c5e20bb470c86a5a9d9c7a9f7404edc1ef796ce Mon Sep 17 00:00:00 2001 From: axzilla Date: Wed, 20 Nov 2024 13:37:47 +0700 Subject: [PATCH 09/17] change: simplify select component --- assets/css/output.css | 148 +-------------- internals/ui/showcase/select.templ | 55 ++---- pkg/components/select.templ | 129 ++----------- pkg/components/select_templ.go | 282 ++++------------------------- pkg/styles/goilerplate.css | 163 +---------------- 5 files changed, 75 insertions(+), 702 deletions(-) diff --git a/assets/css/output.css b/assets/css/output.css index 33f509a..12ba4c4 100644 --- a/assets/css/output.css +++ b/assets/css/output.css @@ -699,10 +699,6 @@ body { left: 50%; } -.left-2 { - left: 0.5rem; -} - .left-full { left: 100%; } @@ -715,6 +711,10 @@ body { right: 0.5rem; } +.right-3 { + right: 0.75rem; +} + .right-4 { right: 1rem; } @@ -731,12 +731,12 @@ body { top: 0.5rem; } -.top-full { - top: 100%; +.top-3 { + top: 0.75rem; } -.start-0 { - inset-inline-start: 0px; +.top-full { + top: 100%; } .z-10 { @@ -796,10 +796,6 @@ body { margin-left: 0.25rem; } -.ml-2 { - margin-left: 0.5rem; -} - .ml-auto { margin-left: auto; } @@ -894,10 +890,6 @@ body { height: 6rem; } -.h-3\.5 { - height: 0.875rem; -} - .h-4 { height: 1rem; } @@ -942,10 +934,6 @@ body { max-height: 24rem; } -.max-h-\[15rem\] { - max-height: 15rem; -} - .max-h-\[50vh\] { max-height: 50vh; } @@ -974,10 +962,6 @@ body { width: 6rem; } -.w-3\.5 { - width: 0.875rem; -} - .w-3\/4 { width: 75%; } @@ -1305,12 +1289,6 @@ body { overflow-y: auto; } -.truncate { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - .whitespace-nowrap { white-space: nowrap; } @@ -1393,20 +1371,10 @@ body { border-color: transparent; } -.border-gray-300 { - --tw-border-opacity: 1; - border-color: rgb(209 213 219 / var(--tw-border-opacity)); -} - .bg-\[--theme-primary\] { background-color: var(--theme-primary); } -.bg-accent { - --tw-bg-opacity: 1; - background-color: hsl(var(--accent) / var(--tw-bg-opacity)); -} - .bg-background { --tw-bg-opacity: 1; background-color: hsl(var(--background) / var(--tw-bg-opacity)); @@ -1488,11 +1456,6 @@ body { background-color: rgb(255 255 255 / var(--tw-bg-opacity)); } -.bg-gray-50 { - --tw-bg-opacity: 1; - background-color: rgb(249 250 251 / var(--tw-bg-opacity)); -} - .bg-opacity-50 { --tw-bg-opacity: 0.5; } @@ -1537,10 +1500,6 @@ body { padding: 1.5rem; } -.p-2\.5 { - padding: 0.625rem; -} - .px-0\.5 { padding-left: 0.125rem; padding-right: 0.125rem; @@ -1576,11 +1535,6 @@ body { padding-bottom: 0.25rem; } -.py-1\.5 { - padding-top: 0.375rem; - padding-bottom: 0.375rem; -} - .py-12 { padding-top: 3rem; padding-bottom: 3rem; @@ -1616,11 +1570,6 @@ body { padding-bottom: 2rem; } -.px-0 { - padding-left: 0px; - padding-right: 0px; -} - .pb-4 { padding-bottom: 1rem; } @@ -1629,14 +1578,6 @@ body { padding-left: 1.5rem; } -.pl-8 { - padding-left: 2rem; -} - -.pr-2 { - padding-right: 0.5rem; -} - .pt-0 { padding-top: 0px; } @@ -1649,14 +1590,6 @@ body { padding-top: 1.25rem; } -.ps-10 { - padding-inline-start: 2.5rem; -} - -.ps-3\.5 { - padding-inline-start: 0.875rem; -} - .text-left { text-align: left; } @@ -1831,11 +1764,6 @@ body { color: rgb(255 255 255 / var(--tw-text-opacity)); } -.text-gray-500 { - --tw-text-opacity: 1; - color: rgb(107 114 128 / var(--tw-text-opacity)); -} - .underline { text-decoration-line: underline; } @@ -1861,10 +1789,6 @@ body { opacity: 1; } -.opacity-50 { - opacity: 0.5; -} - .opacity-80 { opacity: 0.8; } @@ -1881,12 +1805,6 @@ body { box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); } -.shadow-md { - --tw-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1); - --tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); -} - .shadow-sm { --tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05); --tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color); @@ -2226,21 +2144,6 @@ body { opacity: 0.8; } -.focus\:border-blue-500:focus { - --tw-border-opacity: 1; - border-color: rgb(59 130 246 / var(--tw-border-opacity)); -} - -.focus\:bg-accent:focus { - --tw-bg-opacity: 1; - background-color: hsl(var(--accent) / var(--tw-bg-opacity)); -} - -.focus\:text-accent-foreground:focus { - --tw-text-opacity: 1; - color: hsl(var(--accent-foreground) / var(--tw-text-opacity)); -} - .focus\:outline-none:focus { outline: 2px solid transparent; outline-offset: 2px; @@ -2282,11 +2185,6 @@ body { --tw-ring-color: hsl(var(--ring) / var(--tw-ring-opacity)); } -.focus\:ring-blue-500:focus { - --tw-ring-opacity: 1; - --tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity)); -} - .focus\:ring-offset-2:focus { --tw-ring-offset-width: 2px; } @@ -2397,16 +2295,6 @@ body { opacity: 0.7; } -.dark\:border-gray-600:is(.dark *) { - --tw-border-opacity: 1; - border-color: rgb(75 85 99 / var(--tw-border-opacity)); -} - -.dark\:bg-gray-700:is(.dark *) { - --tw-bg-opacity: 1; - background-color: rgb(55 65 81 / var(--tw-bg-opacity)); -} - .dark\:from-gray-900:is(.dark *) { --tw-gradient-from: #111827 var(--tw-gradient-from-position); --tw-gradient-to: rgb(17 24 39 / 0) var(--tw-gradient-to-position); @@ -2437,16 +2325,6 @@ body { color: rgb(255 255 255 / var(--tw-text-opacity)); } -.dark\:placeholder-gray-400:is(.dark *)::-moz-placeholder { - --tw-placeholder-opacity: 1; - color: rgb(156 163 175 / var(--tw-placeholder-opacity)); -} - -.dark\:placeholder-gray-400:is(.dark *)::placeholder { - --tw-placeholder-opacity: 1; - color: rgb(156 163 175 / var(--tw-placeholder-opacity)); -} - .dark\:file\:text-foreground:is(.dark *)::file-selector-button { --tw-text-opacity: 1; color: hsl(var(--foreground) / var(--tw-text-opacity)); @@ -2457,16 +2335,6 @@ body { background-color: rgb(55 65 81 / var(--tw-bg-opacity)); } -.dark\:focus\:border-blue-500:focus:is(.dark *) { - --tw-border-opacity: 1; - border-color: rgb(59 130 246 / var(--tw-border-opacity)); -} - -.dark\:focus\:ring-blue-500:focus:is(.dark *) { - --tw-ring-opacity: 1; - --tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity)); -} - @media (min-width: 640px) { .sm\:my-8 { margin-top: 2rem; diff --git a/internals/ui/showcase/select.templ b/internals/ui/showcase/select.templ index cf3ecde..c2d2180 100644 --- a/internals/ui/showcase/select.templ +++ b/internals/ui/showcase/select.templ @@ -9,6 +9,19 @@ templ SelectShowcase() {

Default Select

+ @components.Select(components.SelectProps{ + ID: "fruit", + Name: "fruit", + Options: []components.SelectOption{ + {Label: "Apple", Value: "apple"}, + {Label: "Banana", Value: "banana"}, + {Label: "Orange", Value: "orange"}, + {Label: "Mango", Value: "mango"}, + }, + }) +
+
+

With Placeholder

@components.Select(components.SelectProps{ ID: "fruit", Name: "fruit", @@ -24,13 +37,14 @@ templ SelectShowcase() {

Selected Value

@components.Select(components.SelectProps{ - ID: "selected", - Name: "selected", - Value: "banana", + ID: "selected", + Name: "selected", + Placeholder: "Select a fruit", Options: []components.SelectOption{ {Label: "Apple", Value: "apple"}, {Label: "Banana", Value: "banana"}, - {Label: "Orange", Value: "orange"}, + {Label: "Orange", Value: "orange", Attributes: templ.Attributes{"selected": true}}, + {Label: "Mango", Value: "mango"}, }, })
@@ -40,44 +54,13 @@ templ SelectShowcase() { ID: "disabled", Name: "disabled", Placeholder: "Select is disabled", - Disabled: "true", + Attributes: templ.Attributes{":disabled": "true"}, Options: []components.SelectOption{ {Label: "Option 1", Value: "1"}, {Label: "Option 2", Value: "2"}, }, })
-
-

With Disabled Options

- @components.Select(components.SelectProps{ - ID: "disabled-options", - Name: "disabled-options", - Placeholder: "Select an option", - Options: []components.SelectOption{ - {Label: "Available", Value: "available"}, - {Label: "Out of Stock", Value: "out-of-stock", Disabled: "true"}, - {Label: "In Stock", Value: "in-stock"}, - {Label: "Discontinued", Value: "discontinued", Disabled: "true"}, - }, - }) -
-
-

Dynamic Example

-
- @components.Select(components.SelectProps{ - ID: "user-type", - Name: "user-type", - Placeholder: "Select user type", - Value: "userType", - Options: []components.SelectOption{ - {Label: "Admin", Value: "admin"}, - {Label: "User", Value: "user"}, - {Label: "Guest", Value: "guest"}, - }, - }) -

-
-
} diff --git a/pkg/components/select.templ b/pkg/components/select.templ index f33d385..92917df 100644 --- a/pkg/components/select.templ +++ b/pkg/components/select.templ @@ -3,9 +3,7 @@ package components import ( - "fmt" "github.com/axzilla/goilerplate/pkg/icons" - "github.com/axzilla/goilerplate/pkg/utils" ) // SelectProps defines the properties for the Select component. @@ -22,14 +20,6 @@ type SelectProps struct { // Options is the array of available options Options []SelectOption - // Value can be a string containing a JS expression for the selected value - // Example: "selectedValue" or "'banana'" or "user.preference" - Value string - - // Disabled can be a string containing a JS expression - // Example: "isLoading" or "true" - Disabled string - // Class specifies additional CSS classes Class string @@ -45,9 +35,8 @@ type SelectOption struct { // Value is the actual value of the option Value string - // Disabled is a JavaScript expression for the disabled state - // Example: "true" or "isOutOfStock" - Disabled string + // Attributes allows passing additional HTML attributes + Attributes templ.Attributes } // Select renders a custom select component with a button trigger and dropdown menu. @@ -76,126 +65,30 @@ type SelectOption struct { // - Class: Additional CSS classes. Optional. // - Attributes: Additional HTML attributes. Optional. templ Select(props SelectProps) { -
- // Hidden native select for form submission +
- // Custom select button - - // Dropdown menu -
- // Dropdown items -
    - for _, option := range props.Options { -
  • - { option.Label } - - @icons.Check(icons.IconProps{Size: "14"}) - -
  • - } -
+
+ @icons.ChevronDown(icons.IconProps{Size: "16", Class: "text-muted-foreground"})
} diff --git a/pkg/components/select_templ.go b/pkg/components/select_templ.go index 79e614d..df1e75a 100644 --- a/pkg/components/select_templ.go +++ b/pkg/components/select_templ.go @@ -11,9 +11,7 @@ import "github.com/a-h/templ" import templruntime "github.com/a-h/templ/runtime" import ( - "fmt" "github.com/axzilla/goilerplate/pkg/icons" - "github.com/axzilla/goilerplate/pkg/utils" ) // SelectProps defines the properties for the Select component. @@ -30,14 +28,6 @@ type SelectProps struct { // Options is the array of available options Options []SelectOption - // Value can be a string containing a JS expression for the selected value - // Example: "selectedValue" or "'banana'" or "user.preference" - Value string - - // Disabled can be a string containing a JS expression - // Example: "isLoading" or "true" - Disabled string - // Class specifies additional CSS classes Class string @@ -53,9 +43,8 @@ type SelectOption struct { // Value is the actual value of the option Value string - // Disabled is a JavaScript expression for the disabled state - // Example: "true" or "isOutOfStock" - Disabled string + // Attributes allows passing additional HTML attributes + Attributes templ.Attributes } // Select renders a custom select component with a button trigger and dropdown menu. @@ -104,34 +93,16 @@ func Select(props SelectProps) templ.Component { templ_7745c5c3_Var1 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - var templ_7745c5c3_Var2 = []any{utils.TwMerge("relative w-full", props.Class)} - templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var2...) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/pkg/styles/goilerplate.css b/pkg/styles/goilerplate.css index beca0ec..511f659 100644 --- a/pkg/styles/goilerplate.css +++ b/pkg/styles/goilerplate.css @@ -699,10 +699,6 @@ body { left: 50%; } -.left-2 { - left: 0.5rem; -} - .left-full { left: 100%; } @@ -711,6 +707,10 @@ body { right: 0px; } +.right-3 { + right: 0.75rem; +} + .right-4 { right: 1rem; } @@ -723,18 +723,14 @@ body { top: 50%; } -.top-2 { - top: 0.5rem; +.top-3 { + top: 0.75rem; } .top-full { top: 100%; } -.start-0 { - inset-inline-start: 0px; -} - .z-10 { z-index: 10; } @@ -772,10 +768,6 @@ body { margin-left: 0.25rem; } -.ml-2 { - margin-left: 0.5rem; -} - .ml-auto { margin-left: auto; } @@ -858,10 +850,6 @@ body { height: 4rem; } -.h-3\.5 { - height: 0.875rem; -} - .h-4 { height: 1rem; } @@ -894,10 +882,6 @@ body { height: 100%; } -.max-h-\[15rem\] { - max-height: 15rem; -} - .max-h-\[50vh\] { max-height: 50vh; } @@ -918,10 +902,6 @@ body { width: 4rem; } -.w-3\.5 { - width: 0.875rem; -} - .w-3\/4 { width: 75%; } @@ -1152,12 +1132,6 @@ body { overflow-y: auto; } -.truncate { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - .whitespace-nowrap { white-space: nowrap; } @@ -1236,16 +1210,6 @@ body { border-color: transparent; } -.border-gray-300 { - --tw-border-opacity: 1; - border-color: rgb(209 213 219 / var(--tw-border-opacity)); -} - -.bg-accent { - --tw-bg-opacity: 1; - background-color: hsl(var(--accent) / var(--tw-bg-opacity)); -} - .bg-background { --tw-bg-opacity: 1; background-color: hsl(var(--background) / var(--tw-bg-opacity)); @@ -1317,11 +1281,6 @@ body { background-color: hsl(var(--secondary) / var(--tw-bg-opacity)); } -.bg-gray-50 { - --tw-bg-opacity: 1; - background-color: rgb(249 250 251 / var(--tw-bg-opacity)); -} - .bg-opacity-50 { --tw-bg-opacity: 0.5; } @@ -1347,10 +1306,6 @@ body { padding: 1.5rem; } -.p-2\.5 { - padding: 0.625rem; -} - .px-0\.5 { padding-left: 0.125rem; padding-right: 0.125rem; @@ -1381,11 +1336,6 @@ body { padding-bottom: 0.25rem; } -.py-1\.5 { - padding-top: 0.375rem; - padding-bottom: 0.375rem; -} - .py-2 { padding-top: 0.5rem; padding-bottom: 0.5rem; @@ -1406,23 +1356,10 @@ body { padding-bottom: 1.5rem; } -.px-0 { - padding-left: 0px; - padding-right: 0px; -} - .pb-4 { padding-bottom: 1rem; } -.pl-8 { - padding-left: 2rem; -} - -.pr-2 { - padding-right: 0.5rem; -} - .pt-0 { padding-top: 0px; } @@ -1431,14 +1368,6 @@ body { padding-top: 1.25rem; } -.ps-10 { - padding-inline-start: 2.5rem; -} - -.ps-3\.5 { - padding-inline-start: 0.875rem; -} - .text-left { text-align: left; } @@ -1573,16 +1502,6 @@ body { color: hsl(var(--secondary-foreground) / var(--tw-text-opacity)); } -.text-gray-500 { - --tw-text-opacity: 1; - color: rgb(107 114 128 / var(--tw-text-opacity)); -} - -.text-gray-900 { - --tw-text-opacity: 1; - color: rgb(17 24 39 / var(--tw-text-opacity)); -} - .underline { text-decoration-line: underline; } @@ -1604,10 +1523,6 @@ body { opacity: 1; } -.opacity-50 { - opacity: 0.5; -} - .opacity-80 { opacity: 0.8; } @@ -1624,12 +1539,6 @@ body { box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); } -.shadow-md { - --tw-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1); - --tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); -} - .shadow-sm { --tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05); --tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color); @@ -1950,21 +1859,6 @@ body { opacity: 1; } -.focus\:border-blue-500:focus { - --tw-border-opacity: 1; - border-color: rgb(59 130 246 / var(--tw-border-opacity)); -} - -.focus\:bg-accent:focus { - --tw-bg-opacity: 1; - background-color: hsl(var(--accent) / var(--tw-bg-opacity)); -} - -.focus\:text-accent-foreground:focus { - --tw-text-opacity: 1; - color: hsl(var(--accent-foreground) / var(--tw-text-opacity)); -} - .focus\:outline-none:focus { outline: 2px solid transparent; outline-offset: 2px; @@ -2006,11 +1900,6 @@ body { --tw-ring-color: hsl(var(--ring) / var(--tw-ring-opacity)); } -.focus\:ring-blue-500:focus { - --tw-ring-opacity: 1; - --tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity)); -} - .focus\:ring-offset-2:focus { --tw-ring-offset-width: 2px; } @@ -2111,41 +2000,11 @@ body { opacity: 0.5; } -.dark\:border-gray-600:is(.dark *) { - --tw-border-opacity: 1; - border-color: rgb(75 85 99 / var(--tw-border-opacity)); -} - -.dark\:bg-gray-700:is(.dark *) { - --tw-bg-opacity: 1; - background-color: rgb(55 65 81 / var(--tw-bg-opacity)); -} - .dark\:text-gray-200:is(.dark *) { --tw-text-opacity: 1; color: rgb(229 231 235 / var(--tw-text-opacity)); } -.dark\:text-gray-400:is(.dark *) { - --tw-text-opacity: 1; - color: rgb(156 163 175 / var(--tw-text-opacity)); -} - -.dark\:text-white:is(.dark *) { - --tw-text-opacity: 1; - color: rgb(255 255 255 / var(--tw-text-opacity)); -} - -.dark\:placeholder-gray-400:is(.dark *)::-moz-placeholder { - --tw-placeholder-opacity: 1; - color: rgb(156 163 175 / var(--tw-placeholder-opacity)); -} - -.dark\:placeholder-gray-400:is(.dark *)::placeholder { - --tw-placeholder-opacity: 1; - color: rgb(156 163 175 / var(--tw-placeholder-opacity)); -} - .dark\:file\:text-foreground:is(.dark *)::file-selector-button { --tw-text-opacity: 1; color: hsl(var(--foreground) / var(--tw-text-opacity)); @@ -2156,16 +2015,6 @@ body { background-color: rgb(55 65 81 / var(--tw-bg-opacity)); } -.dark\:focus\:border-blue-500:focus:is(.dark *) { - --tw-border-opacity: 1; - border-color: rgb(59 130 246 / var(--tw-border-opacity)); -} - -.dark\:focus\:ring-blue-500:focus:is(.dark *) { - --tw-ring-opacity: 1; - --tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity)); -} - @media (min-width: 640px) { .sm\:my-8 { margin-top: 2rem; From 00a8017d506bbd950031dd0556d5a0e9ccf3952d Mon Sep 17 00:00:00 2001 From: axzilla Date: Wed, 20 Nov 2024 15:13:05 +0700 Subject: [PATCH 10/17] change: improve and simplify input component --- internals/ui/showcase/input.templ | 71 ++++++------- pkg/components/input.templ | 59 ++++++++--- pkg/components/input_templ.go | 171 +++++++++++++++++++++++++----- pkg/styles/goilerplate.css | 8 ++ 4 files changed, 230 insertions(+), 79 deletions(-) diff --git a/internals/ui/showcase/input.templ b/internals/ui/showcase/input.templ index 5a01155..b6f8992 100644 --- a/internals/ui/showcase/input.templ +++ b/internals/ui/showcase/input.templ @@ -7,9 +7,15 @@ templ InputShowcase() {

Default

+ @components.Input(components.InputProps{ + Type: "email", + }) +
+
+

With Placeholder

@components.Input(components.InputProps{ Type: "email", - Placeholder: "Email", + Placeholder: "e.g. john@doe.com", })
@@ -23,54 +29,45 @@ templ InputShowcase() {

Disabled

@components.Input(components.InputProps{ - Type: "email", - Placeholder: "Email", - Attributes: templ.Attributes{"disabled": "true"}, + Type: "email", + Attributes: templ.Attributes{"disabled": "true"}, })

With Label

- @components.Input(components.InputProps{ - ID: "email", - Type: "email", - Placeholder: "Email", + ID: "email", + Type: "email", + Label: "Email", })
-

With Button

-
- @components.Input(components.InputProps{ - Type: "email", - Placeholder: "Email", - }) - @components.Button(components.ButtonProps{ - Type: "submit", - Text: "Subscribe", - }) -
+

With Description

+ @components.Input(components.InputProps{ + ID: "email", + Type: "email", + Description: "This is your accounts email address.", + })
-

Form

-
-
- - @components.Input(components.InputProps{ - ID: "username", - }) -

This is your public display name.

-
- @components.Button(components.ButtonProps{ - Type: "submit", - Text: "Submit", - }) -
+

With Error

+ @components.Input(components.InputProps{ + ID: "username", + Error: "Username must be more then 2 characters", + }) +
+
+

Advanced

+ @components.Input(components.InputProps{ + ID: "username", + Label: "Username", + Placeholder: "e.g. john123", + Description: "This is your public display name.", + Value: "", + Error: "Username must be more then 2 characters", + })
diff --git a/pkg/components/input.templ b/pkg/components/input.templ index 60e0e22..f04cb9d 100644 --- a/pkg/components/input.templ +++ b/pkg/components/input.templ @@ -41,6 +41,15 @@ type InputProps struct { // Default: "" (empty string) ID string + // Label + Label string + + // Description + Description string + + // Error + Error string + // Class specifies additional CSS classes to apply to the input field. // Default: "" (empty string) Class string @@ -81,22 +90,40 @@ type InputProps struct { // - FileAccept: Specifies which file types are accepted (only for file type). Default: "" (empty string) // - Attributes: Additional HTML attributes to apply to the input element. Default: nil templ Input(props InputProps) { - + if props.Label != "" { + } - if props.Type == InputTypeFile { - accept={ props.FileAccept } + + if props.Description != "" { +

{ props.Description }

} - { props.Attributes... } - /> + if props.Error != "" { +

{ props.Error }

+ } + } diff --git a/pkg/components/input_templ.go b/pkg/components/input_templ.go index fb8d261..75ca9e2 100644 --- a/pkg/components/input_templ.go +++ b/pkg/components/input_templ.go @@ -49,6 +49,15 @@ type InputProps struct { // Default: "" (empty string) ID string + // Label + Label string + + // Description + Description string + + // Error + Error string + // Class specifies additional CSS classes to apply to the input field. // Default: "" (empty string) Class string @@ -109,7 +118,62 @@ func Input(props InputProps) templ.Component { templ_7745c5c3_Var1 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - var templ_7745c5c3_Var2 = []any{ + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if props.Label != "" { + var templ_7745c5c3_Var2 = []any{"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70", + templ.KV("text-destructive", len(props.Error) > 0)} + templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var2...) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + var templ_7745c5c3_Var6 = []any{ utils.TwMerge("flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background", "file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground", "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2", @@ -117,7 +181,7 @@ func Input(props InputProps) templ.Component { "file:text-foreground dark:file:text-foreground", props.Class), } - templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var2...) + templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var6...) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -125,12 +189,12 @@ func Input(props InputProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var3 string - templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(string(props.Type)) + var templ_7745c5c3_Var7 string + templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(string(props.Type)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/components/input.templ`, Line: 85, Col: 27} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/components/input.templ`, Line: 104, Col: 28} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -138,12 +202,12 @@ func Input(props InputProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var4 string - templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(props.Placeholder) + var templ_7745c5c3_Var8 string + templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(props.Placeholder) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/components/input.templ`, Line: 86, Col: 33} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/components/input.templ`, Line: 105, Col: 34} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -151,12 +215,25 @@ func Input(props InputProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var5 string - templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(props.Name) + var templ_7745c5c3_Var9 string + templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(props.Name) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/components/input.templ`, Line: 87, Col: 19} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/components/input.templ`, Line: 106, Col: 20} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" value=\"") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var10 string + templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(props.Value) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/components/input.templ`, Line: 107, Col: 22} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -164,12 +241,12 @@ func Input(props InputProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var6 string - templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(props.ID) + var templ_7745c5c3_Var11 string + templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(props.ID) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/components/input.templ`, Line: 88, Col: 15} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/components/input.templ`, Line: 108, Col: 16} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -177,12 +254,12 @@ func Input(props InputProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var7 string - templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var2).String()) + var templ_7745c5c3_Var12 string + templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var6).String()) if templ_7745c5c3_Err != nil { return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/components/input.templ`, Line: 1, Col: 0} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -195,12 +272,12 @@ func Input(props InputProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var8 string - templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(props.FileAccept) + var templ_7745c5c3_Var13 string + templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(props.FileAccept) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/components/input.templ`, Line: 98, Col: 28} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/components/input.templ`, Line: 118, Col: 29} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -213,7 +290,49 @@ func Input(props InputProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(">") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("> ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if props.Description != "" { + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("

") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var14 string + templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(props.Description) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/components/input.templ`, Line: 123, Col: 67} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("

") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + if props.Error != "" { + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("

") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var15 string + templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(props.Error) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/components/input.templ`, Line: 126, Col: 64} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("

") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/pkg/styles/goilerplate.css b/pkg/styles/goilerplate.css index 511f659..bc7dcb3 100644 --- a/pkg/styles/goilerplate.css +++ b/pkg/styles/goilerplate.css @@ -743,6 +743,10 @@ body { z-index: 50; } +.m-0 { + margin: 0px; +} + .mx-auto { margin-left: auto; margin-right: auto; @@ -2000,6 +2004,10 @@ body { opacity: 0.5; } +.peer:disabled ~ .peer-disabled\:opacity-70 { + opacity: 0.7; +} + .dark\:text-gray-200:is(.dark *) { --tw-text-opacity: 1; color: rgb(229 231 235 / var(--tw-text-opacity)); From 1a0c70f7506c1eeef59f20feecc8dde397422afb Mon Sep 17 00:00:00 2001 From: axzilla Date: Thu, 21 Nov 2024 15:11:52 +0700 Subject: [PATCH 11/17] feat: add textarea component --- assets/css/output.css | 20 + cmd/server/main.go | 1 + internals/shared/menudata.go | 4 + internals/ui/pages/textarea.templ | 39 + internals/ui/showcase/textarea.templ | 73 + pkg/components/textarea.templ | 84 + pkg/components/textarea_templ.go | 291 + pkg/styles/goilerplate.css | 12 + repopack-output.txt | 9950 ++++++++++++++++++++++++++ 9 files changed, 10474 insertions(+) create mode 100644 internals/ui/pages/textarea.templ create mode 100644 internals/ui/showcase/textarea.templ create mode 100644 pkg/components/textarea.templ create mode 100644 pkg/components/textarea_templ.go create mode 100644 repopack-output.txt diff --git a/assets/css/output.css b/assets/css/output.css index 12ba4c4..e0d4855 100644 --- a/assets/css/output.css +++ b/assets/css/output.css @@ -645,6 +645,10 @@ body { pointer-events: none; } +.visible { + visibility: visible; +} + .invisible { visibility: hidden; } @@ -938,6 +942,10 @@ body { max-height: 50vh; } +.min-h-\[80px\] { + min-height: 80px; +} + .min-h-screen { min-height: 100vh; } @@ -1006,6 +1014,10 @@ body { max-width: 80rem; } +.max-w-lg { + max-width: 32rem; +} + .max-w-md { max-width: 28rem; } @@ -1038,6 +1050,10 @@ body { flex-shrink: 0; } +.grow { + flex-grow: 1; +} + .-translate-x-1 { --tw-translate-x: -0.25rem; transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); @@ -1123,6 +1139,10 @@ body { user-select: none; } +.resize { + resize: both; +} + .list-decimal { list-style-type: decimal; } diff --git a/cmd/server/main.go b/cmd/server/main.go index 142e3bc..936349f 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -39,6 +39,7 @@ func main() { mux.Handle("GET /docs/components/select", templ.Handler(pages.Select())) mux.Handle("GET /docs/components/sheet", templ.Handler(pages.Sheet())) mux.Handle("GET /docs/components/tabs", templ.Handler(pages.Tabs())) + mux.Handle("GET /docs/components/textarea", templ.Handler(pages.Textarea())) mux.Handle("GET /docs/components/toggle", templ.Handler(pages.Toggle())) fmt.Println("Server is running on http://localhost:8090") diff --git a/internals/shared/menudata.go b/internals/shared/menudata.go index b7474b2..5e8c81f 100644 --- a/internals/shared/menudata.go +++ b/internals/shared/menudata.go @@ -98,6 +98,10 @@ var Sections = []Section{ Text: "Tabs", Href: "/docs/components/tabs", }, + { + Text: "Textarea", + Href: "/docs/components/textarea", + }, { Text: "Toggle", Href: "/docs/components/toggle", diff --git a/internals/ui/pages/textarea.templ b/internals/ui/pages/textarea.templ new file mode 100644 index 0000000..3edc93e --- /dev/null +++ b/internals/ui/pages/textarea.templ @@ -0,0 +1,39 @@ +package pages + +import ( + "github.com/axzilla/goilerplate/internals/ui/layouts" + "github.com/axzilla/goilerplate/internals/ui/showcase" + "github.com/axzilla/goilerplate/pkg/components" +) + +templ Textarea() { + @layouts.DocsLayout() { +
+
+

Textarea

+

A multi-line text input field that allows users to enter longer text content.

+
+ @components.Tabs(components.TabsProps{ + Tabs: []components.Tab{ + { + ID: "preview", + Title: "Preview", + Content: showcase.TextareaShowcase(), + }, + { + ID: "code", + Title: "Code", + Content: CodeSnippetFromEmbedded("textarea.templ", "go", showcase.TemplFiles), + }, + { + ID: "component", + Title: "Component", + Content: CodeSnippetFromEmbedded("textarea.templ", "go", components.TemplFiles), + }, + }, + TabsContainerClass: "md:w-1/2", + ContentContainerClass: "w-full", + }) +
+ } +} diff --git a/internals/ui/showcase/textarea.templ b/internals/ui/showcase/textarea.templ new file mode 100644 index 0000000..de64770 --- /dev/null +++ b/internals/ui/showcase/textarea.templ @@ -0,0 +1,73 @@ +// internals/ui/showcase/textarea.templ + +package showcase + +import "github.com/axzilla/goilerplate/pkg/components" + +templ TextareaShowcase() { +
+
+
+

Default Textarea (3 rows)

+ @components.Textarea(components.TextareaProps{ + ID: "default", + Name: "default", + Placeholder: "Type your message here.", + }) +
+
+

Tall Textarea (6 rows)

+ @components.Textarea(components.TextareaProps{ + ID: "tall", + Name: "tall", + Placeholder: "Type your message here.", + Rows: 6, + }) +
+
+

With Label & Description

+ @components.Textarea(components.TextareaProps{ + ID: "with-label", + Name: "with-label", + Label: "Your Message", + Description: "Write a detailed description of your request.", + Placeholder: "Type your message here.", + Rows: 4, + }) +
+
+

With Error

+ @components.Textarea(components.TextareaProps{ + ID: "with-error", + Name: "with-error", + Label: "Your Message", + Error: "Message is required", + Placeholder: "Type your message here.", + }) +
+
+

Auto-resize

+ @components.Textarea(components.TextareaProps{ + ID: "auto-resize", + Name: "auto-resize", + Label: "Auto-resizing Textarea", + Description: "This textarea will grow as you type.", + Placeholder: "Start typing to see the magic...", + Rows: 3, + AutoResize: true, + }) +
+
+

Disabled

+ @components.Textarea(components.TextareaProps{ + ID: "disabled", + Name: "disabled", + Label: "Disabled Textarea", + Value: "This textarea is disabled", + Rows: 3, + Attributes: templ.Attributes{"disabled": "true"}, + }) +
+
+
+} diff --git a/pkg/components/textarea.templ b/pkg/components/textarea.templ new file mode 100644 index 0000000..7c5dbe1 --- /dev/null +++ b/pkg/components/textarea.templ @@ -0,0 +1,84 @@ +package components + +import "github.com/axzilla/goilerplate/pkg/utils" +import "strconv" + +// TextareaProps defines the properties for the Textarea component +type TextareaProps struct { + // ID is the unique identifier for the textarea + ID string + + // Name is the name attribute for the textarea + Name string + + // Value is the initial content of the textarea + Value string + + // Placeholder is shown when the textarea is empty + Placeholder string + + // Label displays a label above the textarea + Label string + + // Description shows helper text below the textarea + Description string + + // Error displays error message below the textarea + Error string + + // Rows sets the initial number of visible text lines + // Default: 3 + Rows int + + // Class allows adding custom CSS classes + Class string + + // AutoResize enables/disables automatic height adjustment + AutoResize bool + + // Attributes allows passing additional HTML attributes + Attributes templ.Attributes +} + +// Textarea renders a textarea component with optional label, description and error message +templ Textarea(props TextareaProps) { +
+ if props.Label != "" { + + } + + if props.Description != "" { +

{ props.Description }

+ } + if props.Error != "" { +

{ props.Error }

+ } +
+} diff --git a/pkg/components/textarea_templ.go b/pkg/components/textarea_templ.go new file mode 100644 index 0000000..1594c79 --- /dev/null +++ b/pkg/components/textarea_templ.go @@ -0,0 +1,291 @@ +// Code generated by templ - DO NOT EDIT. + +// templ: version: v0.2.778 +package components + +//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/axzilla/goilerplate/pkg/utils" +import "strconv" + +// TextareaProps defines the properties for the Textarea component +type TextareaProps struct { + // ID is the unique identifier for the textarea + ID string + + // Name is the name attribute for the textarea + Name string + + // Value is the initial content of the textarea + Value string + + // Placeholder is shown when the textarea is empty + Placeholder string + + // Label displays a label above the textarea + Label string + + // Description shows helper text below the textarea + Description string + + // Error displays error message below the textarea + Error string + + // Rows sets the initial number of visible text lines + // Default: 3 + Rows int + + // Class allows adding custom CSS classes + Class string + + // AutoResize enables/disables automatic height adjustment + AutoResize bool + + // Attributes allows passing additional HTML attributes + Attributes templ.Attributes +} + +// Textarea renders a textarea component with optional label, description and error message +func Textarea(props TextareaProps) 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 = templ_7745c5c3_Buffer.WriteString("
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if props.Label != "" { + var templ_7745c5c3_Var2 = []any{"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70", + templ.KV("text-destructive", len(props.Error) > 0)} + templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var2...) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + var templ_7745c5c3_Var6 = []any{utils.TwMerge( + "flex w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background", + "min-h-[80px] placeholder:text-muted-foreground", + "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2", + "disabled:cursor-not-allowed disabled:opacity-50", + props.Class, + )} + templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var6...) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if props.Description != "" { + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("

") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var13 string + templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(props.Description) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/components/textarea.templ`, Line: 78, Col: 63} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("

") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + if props.Error != "" { + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("

") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var14 string + templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(props.Error) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/components/textarea.templ`, Line: 81, Col: 64} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("

") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) +} + +var _ = templruntime.GeneratedTemplate diff --git a/pkg/styles/goilerplate.css b/pkg/styles/goilerplate.css index bc7dcb3..6a5f312 100644 --- a/pkg/styles/goilerplate.css +++ b/pkg/styles/goilerplate.css @@ -645,6 +645,10 @@ body { pointer-events: none; } +.visible { + visibility: visible; +} + .invisible { visibility: hidden; } @@ -890,6 +894,10 @@ body { max-height: 50vh; } +.min-h-\[80px\] { + min-height: 80px; +} + .w-1\/3 { width: 33.333333%; } @@ -1020,6 +1028,10 @@ body { user-select: none; } +.resize { + resize: both; +} + .appearance-none { -webkit-appearance: none; -moz-appearance: none; diff --git a/repopack-output.txt b/repopack-output.txt new file mode 100644 index 0000000..0942e73 --- /dev/null +++ b/repopack-output.txt @@ -0,0 +1,9950 @@ +This file is a merged representation of the entire codebase, combining all repository files into a single document. +Generated by Repopack on: 2024-11-21T07:38:46.975Z + +================================================================ +File Summary +================================================================ + +Purpose: +-------- +This file contains a packed representation of the entire repository's contents. +It is designed to be easily consumable by AI systems for analysis, code review, +or other automated processes. + +File Format: +------------ +The content is organized as follows: +1. This summary section +2. Repository information +3. Repository structure +4. Multiple file entries, each consisting of: + a. A separator line (================) + b. The file path (File: path/to/file) + c. Another separator line + d. The full contents of the file + e. A blank line + +Usage Guidelines: +----------------- +- This file should be treated as read-only. Any changes should be made to the + original repository files, not this packed version. +- When processing this file, use the file path to distinguish + between different files in the repository. +- Be aware that this file may contain sensitive information. Handle it with + the same level of security as you would the original repository. + +Notes: +------ +- Some files may have been excluded based on .gitignore rules and Repopack's + configuration. +- Binary files are not included in this packed representation. Please refer to + the Repository Structure section for a complete list of file paths, including + binary files. + +Additional Info: +---------------- + +For more information about Repopack, visit: https://github.com/yamadashy/repopack + +================================================================ +Repository Structure +================================================================ +cmd/ + icongen/ + main.go + server/ + main.go +internals/ + config/ + config.go + shared/ + menudata.go + ui/ + layouts/ + base.templ + docs.templ + pages/ + accordion.templ + alert.templ + avatar.templ + button.templ + card.templ + checkbox.templ + datepicker.templ + dropdown_menu.templ + form.templ + how_to_use.templ + icon.templ + input.templ + introduction.templ + landing.templ + modal.templ + radio_group.templ + select.templ + sheet.templ + tabs.templ + themes.templ + toggle.templ + showcase/ + accordion.templ + alert.templ + avatar.templ + button.templ + card.templ + checkbox.templ + datepicker.templ + dropdown_menu.templ + embed.go + form.templ + icon.templ + input.templ + modal.templ + radio_group.templ + select.templ + sheet.templ + tabs.templ + toggle.templ +pkg/ + components/ + accordion.templ + alert.templ + avatar.templ + button.templ + card.templ + checkbox.templ + datepicker.templ + dropdown_menu.templ + embed.go + footer.templ + form.templ + input.templ + modal.templ + navbar.templ + radio_group.templ + select.templ + sheet.templ + sidebar_right.templ + sidebar.templ + tabs.templ + themeswitcher.templ + toggle.templ + icons/ + embed.go + icon_defs.go + icons.go + styles/ + goilerplate.css + utils/ + utils.go +.dockerignore +.env.example +.gitignore +CHEATSHEET.md +CONTRIBUTING.md +Dockerfile +go.mod +go.sum +LICENSE +Makefile +README.md +tailwind.config.js +tailwind.config.lib.js + +================================================================ +Repository Files +================================================================ + +================ +File: cmd/icongen/main.go +================ +package main + +import ( + "fmt" + "os" + "path/filepath" + "strings" +) + +const ( + iconDir = "./lucide/icons" // Path to the Lucide SVG files + outputFile = "./pkg/icons/icon_defs.go" + iconContentDir = "./pkg/icons/content" // Directory for individual icon contents +) + +func main() { + // Read all files from the icon directory + files, err := os.ReadDir(iconDir) + if err != nil { + panic(err) + } + + // Initialize slice for icon definitions + var iconDefs []string + iconDefs = append(iconDefs, "package icons\n") + iconDefs = append(iconDefs, "// This file is auto generated\n") + + // Create the content directory if it doesn't exist + err = os.MkdirAll(iconContentDir, os.ModePerm) + if err != nil { + panic(err) + } + + // Process each SVG file + for _, file := range files { + if filepath.Ext(file.Name()) == ".svg" { + name := strings.TrimSuffix(file.Name(), ".svg") + funcName := toPascalCase(name) + + // Add icon definition + iconDefs = append(iconDefs, fmt.Sprintf("var %s = Icon(%q)\n", funcName, name)) + + // Save icon content to a separate file + content, err := os.ReadFile(filepath.Join(iconDir, file.Name())) + if err != nil { + panic(err) + } + + err = os.WriteFile(filepath.Join(iconContentDir, name+".svg"), content, 0644) + if err != nil { + panic(err) + } + } + } + + // Write all icon definitions to the output file + err = os.WriteFile(outputFile, []byte(strings.Join(iconDefs, "")), 0644) + if err != nil { + panic(err) + } + + fmt.Println("Icon definitions and contents generated successfully!") +} + +// toPascalCase converts a kebab-case string to PascalCase +func toPascalCase(s string) string { + words := strings.Split(s, "-") + for i, word := range words { + words[i] = strings.Title(word) + } + return strings.Join(words, "") +} + +================ +File: cmd/server/main.go +================ +package main + +import ( + "fmt" + "net/http" + + "github.com/a-h/templ" + "github.com/axzilla/goilerplate/assets" + "github.com/axzilla/goilerplate/internals/config" + "github.com/axzilla/goilerplate/internals/ui/pages" +) + +func main() { + mux := http.NewServeMux() + config.LoadConfig() + + SetupAssetsRoutes(mux) + + mux.Handle("GET /", templ.Handler(pages.Landing())) + mux.Handle("GET /docs/components", http.RedirectHandler("/docs/components/accordion", http.StatusSeeOther)) + mux.Handle("GET /docs/getting-started", http.RedirectHandler("/docs/introduction", http.StatusSeeOther)) + mux.Handle("GET /docs/introduction", templ.Handler(pages.Introduction())) + mux.Handle("GET /docs/how-to-use", templ.Handler(pages.HowToUse())) + mux.Handle("GET /docs/themes", templ.Handler(pages.Themes())) + // Components + mux.Handle("GET /docs/components/accordion", templ.Handler(pages.Accordion())) + mux.Handle("GET /docs/components/alert", templ.Handler(pages.Alert())) + mux.Handle("GET /docs/components/avatar", templ.Handler(pages.Avatar())) + mux.Handle("GET /docs/components/button", templ.Handler(pages.Button())) + mux.Handle("GET /docs/components/card", templ.Handler(pages.Card())) + mux.Handle("GET /docs/components/checkbox", templ.Handler(pages.Checkbox())) + mux.Handle("GET /docs/components/datepicker", templ.Handler(pages.Datepicker())) + mux.Handle("GET /docs/components/dropdown-menu", templ.Handler(pages.DropdownMenu())) + mux.Handle("GET /docs/components/form", templ.Handler(pages.Form())) + mux.Handle("GET /docs/components/icon", templ.Handler(pages.Icon())) + mux.Handle("GET /docs/components/input", templ.Handler(pages.Input())) + mux.Handle("GET /docs/components/modal", templ.Handler(pages.Modal())) + mux.Handle("GET /docs/components/radio-group", templ.Handler(pages.RadioGroup())) + mux.Handle("GET /docs/components/select", templ.Handler(pages.Select())) + mux.Handle("GET /docs/components/sheet", templ.Handler(pages.Sheet())) + mux.Handle("GET /docs/components/tabs", templ.Handler(pages.Tabs())) + mux.Handle("GET /docs/components/toggle", templ.Handler(pages.Toggle())) + + fmt.Println("Server is running on http://localhost:8090") + http.ListenAndServe(":8090", mux) +} + +func SetupAssetsRoutes(mux *http.ServeMux) { + var isDevelopment = config.AppConfig.GoEnv != "production" + + // We need this for Templ to work + disableCacheInDevMode := func(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if isDevelopment { + w.Header().Set("Cache-Control", "no-store") + } + next.ServeHTTP(w, r) + }) + } + + // Serve static files from the assets directory + var fs http.Handler + if isDevelopment { + fs = http.FileServer(http.Dir("./assets")) + } else { + fs = http.FileServer(http.FS(assets.Assets)) + } + + mux.Handle("GET /assets/*", disableCacheInDevMode(http.StripPrefix("/assets/", fs))) +} + +================ +File: internals/config/config.go +================ +package config + +import ( + "fmt" + "log" + "os" + + "github.com/joho/godotenv" +) + +type Config struct { + GoEnv string +} + +var AppConfig *Config + +func LoadConfig() { + err := godotenv.Load() + if err != nil { + fmt.Println("Error loading .env file") + } else { + log.Println(".env file initialized.") + } + + AppConfig = &Config{ + GoEnv: os.Getenv("GO_ENV"), + } +} + +================ +File: internals/shared/menudata.go +================ +package shared + +type SideLink struct { + Text string + Href string + Icon string + Click string +} + +type Section struct { + Title string + Links []SideLink +} + +var Sections = []Section{ + { + Title: "Getting Started", + Links: []SideLink{ + { + Text: "Introduction", + Href: "/docs/introduction", + }, + { + Text: "How to Use", + Href: "/docs/how-to-use", + }, + { + Text: "Themes", + Href: "/docs/themes", + }, + }, + }, + { + Title: "Components", + Links: []SideLink{ + { + Text: "Accordion", + Href: "/docs/components/accordion", + }, + { + Text: "Alert", + Href: "/docs/components/alert", + }, + { + Text: "Avatar", + Href: "/docs/components/avatar", + }, + { + Text: "Button", + Href: "/docs/components/button", + }, + { + Text: "Card", + Href: "/docs/components/card", + }, + { + Text: "Checkbox", + Href: "/docs/components/checkbox", + }, + { + Text: "Datepicker", + Href: "/docs/components/datepicker", + }, + { + Text: "Dropdown Menu", + Href: "/docs/components/dropdown-menu", + }, + { + Text: "Form", + Href: "/docs/components/form", + }, + + { + Text: "Icon", + Href: "/docs/components/icon", + }, + { + Text: "Input", + Href: "/docs/components/input", + }, + { + Text: "Modal", + Href: "/docs/components/modal", + }, + { + Text: "Radio Group", + Href: "/docs/components/radio-group", + }, + { + Text: "Select", + Href: "/docs/components/select", + }, + { + Text: "Sheet", + Href: "/docs/components/sheet", + }, + { + Text: "Tabs", + Href: "/docs/components/tabs", + }, + { + Text: "Toggle", + Href: "/docs/components/toggle", + }, + }, + }, +} + +================ +File: internals/ui/layouts/base.templ +================ +package layouts + +import "github.com/axzilla/goilerplate/internals/config" + +templ BaseLayout() { + + + + Goilerplate - Modern UI Components for Go & Templ + + + + + if config.AppConfig.GoEnv == "production" { + + + } + + + + + + + + // Theme Customizer + + + + + + + + + + +
+ { children... } +
+ + +} + +================ +File: internals/ui/layouts/docs.templ +================ +package layouts + +import "github.com/axzilla/goilerplate/pkg/components" + +templ DocsLayout() { + @BaseLayout() { +
+
+ @components.Navbar() +
+
+ +
+
+ { children... } +
+
+ +
+
+ @components.Footer() + } +} + +================ +File: internals/ui/pages/accordion.templ +================ +package pages + +import ( + "github.com/axzilla/goilerplate/internals/ui/layouts" + "github.com/axzilla/goilerplate/internals/ui/showcase" + "github.com/axzilla/goilerplate/pkg/components" +) + +templ Accordion() { + @layouts.DocsLayout() { +
+
+

Accordion

+

A vertically stacked set of interactive headings that each reveal a section of content.

+
+ @components.Tabs(components.TabsProps{ + Tabs: []components.Tab{ + { + ID: "preview", + Title: "Preview", + Content: showcase.AccordionShowcase(), + }, + { + ID: "code", + Title: "Code", + Content: CodeSnippetFromEmbedded("accordion.templ", "go", showcase.TemplFiles), + }, + { + ID: "component", + Title: "Component", + Content: CodeSnippetFromEmbedded("accordion.templ", "go", components.TemplFiles), + }, + }, + TabsContainerClass: "md:w-1/2", + ContentContainerClass: "w-full", + }) +
+ } +} + +================ +File: internals/ui/pages/alert.templ +================ +package pages + +import ( + "github.com/axzilla/goilerplate/internals/ui/layouts" + "github.com/axzilla/goilerplate/internals/ui/showcase" + "github.com/axzilla/goilerplate/pkg/components" +) + +templ Alert() { + @layouts.DocsLayout() { +
+
+

Alert

+

Displays a callout for user attention, often used for notifications, warnings, or important messages.

+
+ @components.Tabs(components.TabsProps{ + Tabs: []components.Tab{ + { + ID: "preview", + Title: "Preview", + Content: showcase.AlertShowcase(), + }, + { + ID: "code", + Title: "Code", + Content: CodeSnippetFromEmbedded("alert.templ", "go", showcase.TemplFiles), + }, + { + ID: "component", + Title: "Component", + Content: CodeSnippetFromEmbedded("alert.templ", "go", components.TemplFiles), + }, + }, + TabsContainerClass: "md:w-1/2", + ContentContainerClass: "w-full", + }) +
+ } +} + +================ +File: internals/ui/pages/avatar.templ +================ +package pages + +import ( + "github.com/axzilla/goilerplate/internals/ui/layouts" + "github.com/axzilla/goilerplate/internals/ui/showcase" + "github.com/axzilla/goilerplate/pkg/components" +) + +templ Avatar() { + @layouts.DocsLayout() { +
+
+

Avatar

+

An image element with a fallback for representing the user.

+
+ @components.Tabs(components.TabsProps{ + Tabs: []components.Tab{ + { + ID: "preview", + Title: "Preview", + Content: showcase.AvatarShowcase(), + }, + { + ID: "code", + Title: "Code", + Content: CodeSnippetFromEmbedded("avatar.templ", "go", showcase.TemplFiles), + }, + { + ID: "component", + Title: "Component", + Content: CodeSnippetFromEmbedded("avatar.templ", "go", components.TemplFiles), + }, + }, + TabsContainerClass: "md:w-1/2", + ContentContainerClass: "w-full", + }) +
+ } +} + +================ +File: internals/ui/pages/button.templ +================ +package pages + +import ( + "embed" + "github.com/axzilla/goilerplate/internals/ui/layouts" + "github.com/axzilla/goilerplate/internals/ui/showcase" + "github.com/axzilla/goilerplate/pkg/components" +) + +templ Button() { + @layouts.DocsLayout() { +
+
+

Button

+

Displays a button or a component that looks like a button.

+
+ @components.Tabs(components.TabsProps{ + Tabs: []components.Tab{ + { + ID: "preview", + Title: "Preview", + Content: showcase.ButtonShowcase(), + }, + { + ID: "code", + Title: "Code", + Content: CodeSnippetFromEmbedded("button.templ", "go", showcase.TemplFiles), + }, + { + ID: "component", + Title: "Component", + Content: CodeSnippetFromEmbedded("button.templ", "go", components.TemplFiles), + }, + }, + TabsContainerClass: "md:w-1/2", + ContentContainerClass: "w-full", + }) +
+ } +} + +templ CodeSnippetFromEmbedded(filename, language string, embed embed.FS) { + if content, err := embed.ReadFile(filename); err != nil { +
Error reading file: { filename }: { err.Error() }
+ } else { + @CodeSnippet(string(content), language) + } +} + +templ CodeSnippet(content, language string) { +
+
+			
+				{ content }
+			
+		
+ +
+} + +================ +File: internals/ui/pages/card.templ +================ +package pages + +import ( + "github.com/axzilla/goilerplate/internals/ui/layouts" + "github.com/axzilla/goilerplate/internals/ui/showcase" + "github.com/axzilla/goilerplate/pkg/components" +) + +templ Card() { + @layouts.DocsLayout() { +
+
+

Card

+

Displays a card with header, content, and footer.

+
+ @components.Tabs(components.TabsProps{ + Tabs: []components.Tab{ + { + ID: "preview", + Title: "Preview", + Content: showcase.CardShowcase(), + }, + { + ID: "code", + Title: "Code", + Content: CodeSnippetFromEmbedded("card.templ", "go", showcase.TemplFiles), + }, + { + ID: "component", + Title: "Component", + Content: CodeSnippetFromEmbedded("card.templ", "go", components.TemplFiles), + }, + }, + TabsContainerClass: "md:w-1/2", + ContentContainerClass: "w-full", + }) +
+ } +} + +================ +File: internals/ui/pages/checkbox.templ +================ +package pages + +import ( + "github.com/axzilla/goilerplate/internals/ui/layouts" + "github.com/axzilla/goilerplate/internals/ui/showcase" + "github.com/axzilla/goilerplate/pkg/components" +) + +templ Checkbox() { + @layouts.DocsLayout() { +
+
+

Checkbox

+

A control that allows the user to toggle between checked and not checked.

+
+ @components.Tabs(components.TabsProps{ + Tabs: []components.Tab{ + { + ID: "preview", + Title: "Preview", + Content: showcase.CheckboxShowcase(), + }, + { + ID: "code", + Title: "Code", + Content: CodeSnippetFromEmbedded("checkbox.templ", "go", showcase.TemplFiles), + }, + { + ID: "component", + Title: "Component", + Content: CodeSnippetFromEmbedded("checkbox.templ", "go", components.TemplFiles), + }, + }, + TabsContainerClass: "md:w-1/2", + ContentContainerClass: "w-full", + }) +
+ } +} + +================ +File: internals/ui/pages/datepicker.templ +================ +package pages + +import ( + "github.com/axzilla/goilerplate/internals/ui/layouts" + "github.com/axzilla/goilerplate/internals/ui/showcase" + "github.com/axzilla/goilerplate/pkg/components" +) + +templ Datepicker() { + @layouts.DocsLayout() { +
+
+

Datepicker

+

A date picker component.

+
+ @components.Tabs(components.TabsProps{ + Tabs: []components.Tab{ + { + ID: "preview", + Title: "Preview", + Content: showcase.DatepickerShowcase(), + }, + { + ID: "code", + Title: "Code", + Content: CodeSnippetFromEmbedded("datepicker.templ", "go", showcase.TemplFiles), + }, + { + ID: "component", + Title: "Component", + Content: CodeSnippetFromEmbedded("datepicker.templ", "go", components.TemplFiles), + }, + }, + TabsContainerClass: "md:w-1/2", + ContentContainerClass: "w-full", + }) +
+ } +} + +================ +File: internals/ui/pages/dropdown_menu.templ +================ +package pages + +import ( + "github.com/axzilla/goilerplate/pkg/components" + "github.com/axzilla/goilerplate/internals/ui/layouts" + "github.com/axzilla/goilerplate/internals/ui/showcase" +) + +templ DropdownMenu() { + @layouts.DocsLayout() { +
+
+

Dropdown Menu

+

The Dropdown Menu component provides a way to display a list of options in a compact form.

+
+ @components.Tabs(components.TabsProps{ + Tabs: []components.Tab{ + { + ID: "preview", + Title: "Preview", + Content: showcase.DropdownMenuShowcase(), + }, + { + ID: "code", + Title: "Code", + Content: CodeSnippetFromEmbedded("dropdown_menu.templ", "go", showcase.TemplFiles), + }, + { + ID: "component", + Title: "Component", + Content: CodeSnippetFromEmbedded("dropdown_menu.templ", "go", components.TemplFiles), + }, + }, + TabsContainerClass: "md:w-1/2", + ContentContainerClass: "w-full", + }) +
+ } +} + +================ +File: internals/ui/pages/form.templ +================ +package pages + +import ( + "github.com/axzilla/goilerplate/internals/ui/layouts" + "github.com/axzilla/goilerplate/internals/ui/showcase" + "github.com/axzilla/goilerplate/pkg/components" +) + +templ Form() { + @layouts.DocsLayout() { +
+
+

Form

+

Building forms with Go, Templ & Alpine.js.

+
+ @components.Tabs(components.TabsProps{ + Tabs: []components.Tab{ + { + ID: "preview", + Title: "Preview", + Content: showcase.FormShowcase(), + }, + { + ID: "code", + Title: "Code", + Content: CodeSnippetFromEmbedded("form.templ", "go", showcase.TemplFiles), + }, + { + ID: "component", + Title: "Component", + Content: CodeSnippetFromEmbedded("form.templ", "go", components.TemplFiles), + }, + }, + TabsContainerClass: "md:w-1/2", + ContentContainerClass: "w-full", + }) +
+ } +} + +================ +File: internals/ui/pages/how_to_use.templ +================ +package pages + +import "github.com/axzilla/goilerplate/internals/ui/layouts" + +templ HowToUse() { + @layouts.DocsLayout() { +
+
+

How To Use

+

Learn how to integrate Goilerplate into your projects.

+
+
+

Two Ways to Use Goilerplate

+

+ Goilerplate offers flexibility in how you can integrate it into your projects. There are two main approaches: +

+
+

1. Use as a Package Library

+

+ Install Goilerplate as a Go package and import components as needed: +

+
+						
+							{ `go get github.com/axzilla/goilerplate
+
+// In your Go files
+import "github.com/axzilla/goilerplate/pkg/components"
+
+// In your Templ files
+@components.Button(components.ButtonProps{Text: "Click me"})` }
+						
+					
+

This method is quick to set up and easy to update, but offers less customization.

+
+
+

2. Copy Components to Your Codebase

+

+ Copy the desired components directly into your project: +

+
    +
  1. Visit our components documentation
  2. +
  3. Find the component you need
  4. +
  5. Copy the component code into your project's components folder
  6. +
+

This method allows for maximum customization but requires manual updates.

+
+
+

Mix and Match

+

+ You can also combine both approaches. For example, use some components as a package and copy others for customization. + This flexibility allows you to balance between ease of use and customization needs. +

+
+
+
+

Quickstart Template

+

+ For a ready-to-go setup, check out our Goilerplate Quickstart template. + This template uses Goilerplate as a package library but can be easily modified to use copied components or a mix of both approaches. +

+
+					
+						{ `git clone https://github.com/axzilla/goilerplate-quickstart.git
+cd goilerplate-quickstart
+
+// Follow the README instructions` }
+					
+				
+
+
+

Manual Setup Requirements

+

+ If you choose to set up Goilerplate manually or copy components, ensure you have the following set up in your project: +

+ +
+
+

Next Steps

+

+ Whichever approach you choose, explore our + + components + + to see code examples and usage details for each Goilerplate component. Feel free to experiment with different integration methods to find what works best for your project! +

+

+ Remember, our components page provides code snippets and usage examples, but for comprehensive documentation on Templ, Tailwind CSS, or Alpine.js, refer to their respective official documentation. +

+
+
+ } +} + +================ +File: internals/ui/pages/icon.templ +================ +package pages + +import ( + "github.com/axzilla/goilerplate/internals/ui/layouts" + "github.com/axzilla/goilerplate/internals/ui/showcase" + "github.com/axzilla/goilerplate/pkg/components" +) + +templ Icon() { + @layouts.DocsLayout() { +
+
+

Icon

+

+ A wrapper for Lucide Icons with optional settings for size, color, fill, stroke, and custom classes. Browse available icons in the Lucide library to see what you can use. +

+
+ @components.Tabs(components.TabsProps{ + Tabs: []components.Tab{ + { + ID: "preview", + Title: "Preview", + Content: showcase.IconShowcase(), + }, + { + ID: "code", + Title: "Code", + Content: CodeSnippetFromEmbedded("icon.templ", "go", showcase.TemplFiles), + }, + }, + TabsContainerClass: "md:w-1/2", + ContentContainerClass: "w-full", + }) +
+ } +} + +================ +File: internals/ui/pages/input.templ +================ +package pages + +import ( + "github.com/axzilla/goilerplate/internals/ui/layouts" + "github.com/axzilla/goilerplate/internals/ui/showcase" + "github.com/axzilla/goilerplate/pkg/components" +) + +templ Input() { + @layouts.DocsLayout() { +
+

Input

+

Displays a form input field or a component that looks like an input field.

+
+ @components.Tabs(components.TabsProps{ + Tabs: []components.Tab{ + { + ID: "preview", + Title: "Preview", + Content: showcase.InputShowcase(), + }, + { + ID: "code", + Title: "Code", + Content: CodeSnippetFromEmbedded("input.templ", "go", showcase.TemplFiles), + }, + { + ID: "component", + Title: "Component", + Content: CodeSnippetFromEmbedded("input.templ", "go", components.TemplFiles), + }, + }, + TabsContainerClass: "md:w-1/2", + }) + } +} + +================ +File: internals/ui/pages/introduction.templ +================ +package pages + +import "github.com/axzilla/goilerplate/internals/ui/layouts" + +templ Introduction() { + @layouts.DocsLayout() { +
+
+

🎉 Goilerplate

+

Modern UI Components for Go & Templ.

+
+
+

What's this madness?

+

+ Build sleek, interactive web applications with Go and Templ. Seamlessly integrate Alpine.js for enhanced client-side functionality and style effortlessly with Tailwind CSS. Where server-side simplicity meets client-side dynamism. +

+

+ Goilerplate is a wild experiment in bringing the joy of modern UI components to the Go ecosystem. It's like a box of LEGO, but for web dev. And yes, we might have had too much coffee while coding this. +

+

+ We've taken Go, sprinkled some Templ magic, added a dash of Alpine.js, topped it with Tailwind CSS, and voilà! You've got yourself a UI toolkit that'll make JavaScript developers question their life choices. +

+

+ Warning: This project is under heavy development. Expect frequent breaking changes, weird behavior, and possibly code that makes you question our sanity. But hey, that's half the fun, right? +

+

+ We're constantly evolving. Check out our + + release notes + to see what's new and exciting! +

+
+
+

Why Goilerplate?

+

+ Inspired by + + shadcn/ui + , + + Pines UI + , and + + daisyUI + , + Goilerplate brings the philosophy of accessible, customizable components to the Go ecosystem. We've taken the best ideas and adapted them for Go, Templ, Alpine.js, and Tailwind CSS enthusiasts. +

+

+ Our components are designed with accessibility in mind, ensuring your web applications are usable by everyone. And just like our inspirations, every component is fully customizable - tweak them, break them, remake them. It's your playground! +

+
+
+

Where are we headed?

+

+ Honestly? We're not entirely sure yet! We're exploring whether to make Goilerplate a strict port of shadcn/ui or to create a unique blend of various inspirations. This journey is as much about discovery as it is about development. +

+

+ What we do know is this: We're committed to providing a flexible, powerful toolkit for Go developers who want to create beautiful, interactive web applications without sacrificing the benefits of server-side rendering. +

+
+
+

Who's to Blame?

+

+ We stand on the shoulders of giants. Big thanks to: +

+
    +
  • Go - For giving us a language that's not JavaScript
  • +
  • Templ - Making templates great again
  • +
  • Alpine.js - JavaScript's cool, minimalist cousin
  • +
  • Tailwind CSS - For saving us from actually writing CSS
  • +
  • shadcn/ui - Major inspiration and component ideas
  • +
  • Pines UI - More inspiration and eye candy
  • +
  • daisyUI - For showing us the power of Tailwind components
  • +
+
+
+ } +} + +================ +File: internals/ui/pages/landing.templ +================ +package pages + +import ( + "github.com/axzilla/goilerplate/internals/ui/layouts" + "github.com/axzilla/goilerplate/pkg/components" +) + +templ Landing() { + @layouts.BaseLayout() { +
+
+

+ Goilerplate +

+

+ Modern UI Components for Go & Templ +

+

+ Craft powerful, responsive web applications with Go and Templ. + Enhance interactivity with Alpine.js and style effortlessly with Tailwind CSS. + Goilerplate bridges the gap between backend robustness and frontend dynamism. +

+ @components.Button(components.ButtonProps{ + Text: "Explore Components", + Href: "/docs/components", + Size: "lg", + }) +
+
+ Gopher +
+
+
+ @components.ThemeSwitcher() +
+ } +} + +================ +File: internals/ui/pages/modal.templ +================ +package pages + +import ( + "github.com/axzilla/goilerplate/internals/ui/layouts" + "github.com/axzilla/goilerplate/internals/ui/showcase" + "github.com/axzilla/goilerplate/pkg/components" +) + +templ Modal() { + @layouts.DocsLayout() { +
+
+

Modal

+

A modal dialog component for displaying content that requires user interaction.

+
+ @components.Tabs(components.TabsProps{ + Tabs: []components.Tab{ + { + ID: "preview", + Title: "Preview", + Content: showcase.ModalShowcase(), + }, + { + ID: "code", + Title: "Code", + Content: CodeSnippetFromEmbedded("modal.templ", "go", showcase.TemplFiles), + }, + { + ID: "component", + Title: "Component", + Content: CodeSnippetFromEmbedded("modal.templ", "go", components.TemplFiles), + }, + }, + TabsContainerClass: "md:w-1/2", + ContentContainerClass: "w-full", + }) +
+ } +} + +================ +File: internals/ui/pages/radio_group.templ +================ +package pages + +import ( + "github.com/axzilla/goilerplate/internals/ui/layouts" + "github.com/axzilla/goilerplate/internals/ui/showcase" + "github.com/axzilla/goilerplate/pkg/components" +) + +templ RadioGroup() { + @layouts.DocsLayout() { +
+
+

Radio Group

+

A set of radio buttons for selecting a single option from a list.

+
+ @components.Tabs(components.TabsProps{ + Tabs: []components.Tab{ + { + ID: "preview", + Title: "Preview", + Content: showcase.RadioGroupShowcase(), + }, + { + ID: "code", + Title: "Code", + Content: CodeSnippetFromEmbedded("radio_group.templ", "go", showcase.TemplFiles), + }, + { + ID: "component", + Title: "Component", + Content: CodeSnippetFromEmbedded("radio_group.templ", "go", components.TemplFiles), + }, + }, + TabsContainerClass: "md:w-1/2", + ContentContainerClass: "w-full", + }) +
+ } +} + +================ +File: internals/ui/pages/select.templ +================ +package pages + +import ( + "github.com/axzilla/goilerplate/internals/ui/layouts" + "github.com/axzilla/goilerplate/internals/ui/showcase" + "github.com/axzilla/goilerplate/pkg/components" +) + +templ Select() { + @layouts.DocsLayout() { +
+
+

Select

+

+ A dropdown menu for selecting a single value from a list of options. +

+
+ @components.Tabs(components.TabsProps{ + Tabs: []components.Tab{ + { + ID: "preview", + Title: "Preview", + Content: showcase.SelectShowcase(), + }, + { + ID: "code", + Title: "Code", + Content: CodeSnippetFromEmbedded("select.templ", "go", showcase.TemplFiles), + }, + { + ID: "component", + Title: "Component", + Content: CodeSnippetFromEmbedded("select.templ", "go", components.TemplFiles), + }, + }, + TabsContainerClass: "md:w-1/2", + ContentContainerClass: "w-full", + }) +
+ } +} + +================ +File: internals/ui/pages/sheet.templ +================ +package pages + +import ( + "github.com/axzilla/goilerplate/internals/ui/layouts" + "github.com/axzilla/goilerplate/internals/ui/showcase" + "github.com/axzilla/goilerplate/pkg/components" +) + +templ Sheet() { + @layouts.DocsLayout() { +
+
+

Sheet

+

Extends the Dialog component to display content that complements the main content of the screen.

+
+ @components.Tabs(components.TabsProps{ + Tabs: []components.Tab{ + { + ID: "preview", + Title: "Preview", + Content: showcase.SheetShowcase(), + }, + { + ID: "code", + Title: "Code", + Content: CodeSnippetFromEmbedded("sheet.templ", "go", showcase.TemplFiles), + }, + { + ID: "component", + Title: "Component", + Content: CodeSnippetFromEmbedded("sheet.templ", "go", components.TemplFiles), + }, + }, + TabsContainerClass: "md:w-1/2", + ContentContainerClass: "w-full", + }) +
+ } +} + +================ +File: internals/ui/pages/tabs.templ +================ +package pages + +import ( + "github.com/axzilla/goilerplate/internals/ui/layouts" + "github.com/axzilla/goilerplate/internals/ui/showcase" + "github.com/axzilla/goilerplate/pkg/components" +) + +templ Tabs() { + @layouts.DocsLayout() { +
+
+

Tabs

+

A set of layered sections of content—known as tab panels—that are displayed one at a time.

+
+ @components.Tabs(components.TabsProps{ + Tabs: []components.Tab{ + { + ID: "preview", + Title: "Preview", + Content: showcase.TabsShowcase(), + }, + { + ID: "code", + Title: "Code", + Content: CodeSnippetFromEmbedded("tabs.templ", "go", showcase.TemplFiles), + }, + { + ID: "component", + Title: "Component", + Content: CodeSnippetFromEmbedded("tabs.templ", "go", components.TemplFiles), + }, + }, + TabsContainerClass: "md:w-1/2", + ContentContainerClass: "w-full", + }) +
+ } +} + +================ +File: internals/ui/pages/themes.templ +================ +// internals/ui/pages/theme_customizer.templ + +package pages + +import ( + "github.com/axzilla/goilerplate/internals/ui/layouts" + "github.com/axzilla/goilerplate/pkg/components" + "github.com/axzilla/goilerplate/pkg/icons" +) + +templ Themes() { + @layouts.DocsLayout() { +
+
+

Themes

+

Customize the theme of the UI components.

+
+
+
+
+
+
Customize
+
Pick a style and color for your components.
+
+ @components.Button(components.ButtonProps{ + Size: "icon", + Variant: "ghost", + IconLeft: icons.RotateCcw(icons.IconProps{Size: "14"}), + Attributes: templ.Attributes{ + "@click": "resetTheme", + }, + }) +
+ @ThemeCustomizer(ThemeCustomizerProps{ + CurrentTheme: "orange", + CurrentRadius: "0.5", + CurrentMode: "light", + }) +
+
+
+
Preview
+
This is how your theme will look like.
+
+ @ThemePreview() +
+
+
+ } +} + +templ ThemePreview() { +
+ @components.Card(components.CardProps{}) { + @components.CardHeader() { + @components.CardTitle() { + User Registration + } + @components.CardDescription() { + Please fill out the form below to create your account. + } + } + @components.CardContent() { +
+
+ + @components.Input(components.InputProps{ + ID: "username", + Name: "username", + Type: components.InputTypeText, + Placeholder: "Enter your username", + }) +
+
+ + @components.Input(components.InputProps{ + ID: "email", + Name: "email", + Type: components.InputTypeEmail, + Placeholder: "Enter your email", + }) +
+
+ + @components.Input(components.InputProps{ + ID: "password", + Name: "password", + Type: components.InputTypePassword, + Placeholder: "Enter your password", + }) +
+
+ + @components.Datepicker(components.DatepickerProps{ + ID: "birthdate", + Name: "birthdate", + Placeholder: "Select your birth date", + Format: "YYYY-MM-DD", + }) +
+
+ + @components.RadioGroup(components.RadioGroupProps{Name: "contact-method"}) { + @components.RadioGroupItem(components.RadioGroupItemProps{ + Value: "email", + ID: "contact-email", + Name: "contact-method", + Label: templ.Raw("Email"), + }) + @components.RadioGroupItem(components.RadioGroupItemProps{ + Value: "phone", + ID: "contact-phone", + Name: "contact-method", + Label: templ.Raw("Phone"), + }) + @components.RadioGroupItem(components.RadioGroupItemProps{ + Value: "mail", + ID: "contact-mail", + Name: "contact-method", + Label: templ.Raw("Physical Mail"), + Attributes: templ.Attributes{"disabled": "true"}, + }) + } +
+
+ +
+ @components.Toggle(components.ToggleProps{ + ID: "marketing", + Name: "marketing", + LabelRight: "Receive marketing emails", + }) +
+
+ @components.Toggle(components.ToggleProps{ + ID: "notifications", + Name: "notifications", + LabelRight: "Enable notifications", + Attributes: templ.Attributes{"checked": "true"}, + }) +
+
+ @components.Toggle(components.ToggleProps{ + ID: "beta", + Name: "beta", + LabelRight: "Join beta program", + Attributes: templ.Attributes{"disabled": "true"}, + }) +
+
+
+ @components.Checkbox(components.CheckboxProps{ + ID: "terms", + Name: "terms", + Value: "accepted", + Label: "I agree to the Terms and Conditions", + }) +
+
+ @components.Checkbox(components.CheckboxProps{ + ID: "newsletter", + Name: "newsletter", + Value: "subscribed", + Label: "Subscribe to our newsletter", + }) +
+
+ } + @components.CardFooter() { +
+ @components.Button(components.ButtonProps{ + Text: "Cancel", + Variant: "secondary", + }) + @components.Button(components.ButtonProps{ + Text: "Register", + Variant: "primary", + }) +
+ } + } +
+} + +type ThemeCustomizerProps struct { + CurrentTheme string + CurrentRadius string + CurrentMode string +} + +templ ThemeCustomizer(props ThemeCustomizerProps) { +
+
+ @ThemeSelector() + @RadiusSelector() + @ModeSelector() +
+ @components.ModalTrigger("css-modal") { + @components.Button(components.ButtonProps{Text: "Generate and Copy CSS", FullWidth: true, Attributes: templ.Attributes{ + "@click": "getGeneratedCSS", + }}) + } + @components.Modal(components.ModalProps{ID: "css-modal", Class: "max-w-xl"}) { + @components.ModalHeader() { + Generated CSS Code + } + @components.ModalBody() { +

+			}
+			@components.ModalFooter() {
+				
+ @components.Button(components.ButtonProps{ + Text: "Copy to Clipboard", + Variant: "primary", + Attributes: templ.Attributes{"@click": "copyToClipboard"}, + }) + @components.ModalClose("css-modal") { + @components.Button(components.ButtonProps{ + Text: "Close", + Variant: "secondary", + }) + } +
+ } + } +
+} + +templ ThemeSelector() { +
+ +
+ + + + + + + + + + + + +
+
+} + +templ RadiusSelector() { +
+ +
+ + + + + +
+
+} + +templ ModeSelector() { +
+ +
+ + +
+
+} + +================ +File: internals/ui/pages/toggle.templ +================ +package pages + +import ( + "github.com/axzilla/goilerplate/internals/ui/layouts" + "github.com/axzilla/goilerplate/internals/ui/showcase" + "github.com/axzilla/goilerplate/pkg/components" +) + +templ Toggle() { + @layouts.DocsLayout() { +
+
+

Toggle

+

+ A control that allows users to toggle between two states, typically used for enabling or disabling features. +

+
+ @components.Tabs(components.TabsProps{ + Tabs: []components.Tab{ + { + ID: "preview", + Title: "Preview", + Content: showcase.ToggleShowcase(), + }, + { + ID: "code", + Title: "Code", + Content: CodeSnippetFromEmbedded("toggle.templ", "go", showcase.TemplFiles), + }, + { + ID: "component", + Title: "Component", + Content: CodeSnippetFromEmbedded("toggle.templ", "go", components.TemplFiles), + }, + }, + TabsContainerClass: "md:w-1/2", + ContentContainerClass: "w-full", + }) +
+ } +} + +================ +File: internals/ui/showcase/accordion.templ +================ +package showcase + +import "github.com/axzilla/goilerplate/pkg/components" + +templ AccordionShowcase() { +
+ @components.Accordion(components.AccordionProps{ + Items: []components.AccordionItem{ + { + ID: "item-1", + Trigger: templ.Raw("Is it accessible?"), + Content: templ.Raw("Yes. It adheres to the WAI-ARIA design pattern."), + }, + { + ID: "item-2", + Trigger: templ.Raw("Is it styled?"), + Content: templ.Raw("Yes. It comes with default styles that match the other components' aesthetic."), + }, + { + ID: "item-3", + Trigger: templ.Raw("Is it animated?"), + Content: templ.Raw("Yes. It's animated by default, but you can disable it if you prefer."), + }, + }, + Class: "w-full sm:max-w-[70%]", + }) +
+} + +================ +File: internals/ui/showcase/alert.templ +================ +package showcase + +import ( + "github.com/axzilla/goilerplate/pkg/components" + "github.com/axzilla/goilerplate/pkg/icons" +) + +templ AlertShowcase() { +
+
+
+

Default Alert

+
+ @components.Alert(components.AlertProps{Variant: components.DefaultAlert}) { + @icons.Rocket(icons.IconProps{Size: "16"}) + @components.AlertTitle() { + Note + } + @components.AlertDescription() { + This is a default alert — check it out! + } + } +
+
+
+

Destructive Alert

+
+ @components.Alert(components.AlertProps{Variant: components.DestructiveAlert}) { + @icons.TriangleAlert(icons.IconProps{Size: "16"}) + @components.AlertTitle() { + Error + } + @components.AlertDescription() { + Your session has expired. Please log in again. + } + } +
+
+
+
+} + +================ +File: internals/ui/showcase/avatar.templ +================ +package showcase + +import "github.com/axzilla/goilerplate/pkg/components" + +templ AvatarShowcase() { +
+
+
+

With Image

+
+ @components.Avatar(components.AvatarProps{ + ImageSrc: "https://avatars.githubusercontent.com/u/26936893?v=4", + Name: "John Doe", + Class: "border-2 border-border", + }) +
+
+
+

With Placeholder

+
+ @components.Avatar(components.AvatarProps{ + Name: "The Dude", + }) +
+
+
+

With Sizes

+
+ @components.Avatar(components.AvatarProps{ + ImageSrc: "https://avatars.githubusercontent.com/u/26936893?v=4", + Name: "John Doe", + Size: components.AvatarSizeSmall, + Class: "border-2 border-border", + }) + @components.Avatar(components.AvatarProps{ + ImageSrc: "https://avatars.githubusercontent.com/u/26936893?v=4", + Name: "John Doe", + Class: "border-2 border-border", + }) + @components.Avatar(components.AvatarProps{ + ImageSrc: "https://avatars.githubusercontent.com/u/26936893?v=4", + Name: "John Doe", + Size: components.AvatarSizeLarge, + Class: "border-2 border-border", + }) +
+
+
+
+} + +================ +File: internals/ui/showcase/button.templ +================ +package showcase + +import ( + "github.com/axzilla/goilerplate/pkg/components" + "github.com/axzilla/goilerplate/pkg/icons" +) + +templ ButtonShowcase() { +
+
+
+

Variants

+
+ @components.Button(components.ButtonProps{Text: "Default"}) + @components.Button(components.ButtonProps{Text: "Secondary", Variant: components.Secondary}) + @components.Button(components.ButtonProps{Text: "Destructive", Variant: components.Destructive}) + @components.Button(components.ButtonProps{Text: "Outline", Variant: components.Outline}) + @components.Button(components.ButtonProps{Text: "Ghost", Variant: components.Ghost}) + @components.Button(components.ButtonProps{Text: "Link", Variant: components.Link}) +
+
+
+

Sizes

+
+ @components.Button(components.ButtonProps{Text: "Default"}) + @components.Button(components.ButtonProps{Text: "Small", Size: components.Sm}) + @components.Button(components.ButtonProps{Text: "Large", Size: components.Lg}) + @components.Button(components.ButtonProps{Size: components.ButtonIcon, IconLeft: icons.Rocket(icons.IconProps{Size: "16"})}) +
+
+
+

States

+
+ @components.Button(components.ButtonProps{Text: "Default"}) + // Alpine.js example + @components.Button(components.ButtonProps{Text: "With Click", Attributes: templ.Attributes{"@click": "alert('Hey Dude!')"}}) + // Vanilla JS example + // @components.Button(components.ButtonProps{Text: "With Click", Attributes: templ.Attributes{"onclick": "alert('Hey Dude!')"}}) + @components.Button(components.ButtonProps{Text: "Disabled", Disabled: true}) + // @components.Button(components.ButtonProps{Text: "Disabled", Disabled: "true"}) + @components.Button(components.ButtonProps{Text: "Full Width", Class: "w-full"}) +
+
+
+

With Icon

+
+ @components.Button(components.ButtonProps{ + Text: "Icon Left", + IconLeft: icons.Rocket(icons.IconProps{Size: "16"}), + }) + @components.Button(components.ButtonProps{ + Text: "Icon Right", + IconRight: icons.Rocket(icons.IconProps{Size: "16"}), + }) +
+
+
+
+} + +================ +File: internals/ui/showcase/card.templ +================ +package showcase + +import "github.com/axzilla/goilerplate/pkg/components" + +templ CardShowcase() { +
+ @components.Card(components.CardProps{Class: "w-[350px]"}) { + @components.CardHeader() { + @components.CardTitle() { + Card Title + } + @components.CardDescription() { + Card Description + } + } + @components.CardContent() { +

Card Content

+ } + @components.CardFooter() { + @components.Button(components.ButtonProps{Text: "Action"}) + } + } +
+} + +================ +File: internals/ui/showcase/checkbox.templ +================ +package showcase + +import "github.com/axzilla/goilerplate/pkg/components" + +templ CheckboxShowcase() { +
+
+
+

Default Checkbox

+ @components.Checkbox(components.CheckboxProps{ + ID: "default-checkbox", + Name: "default", + Value: "default", + Label: "Accept terms and conditions", + }) +
+
+

Checked Checkbox

+ @components.Checkbox(components.CheckboxProps{ + ID: "checked-checkbox", + Name: "newsletter", + Value: "subscribe", + Label: "Receive newsletter", + Attributes: templ.Attributes{"checked": "true"}, + }) +
+
+

Disabled Checkbox

+ @components.Checkbox(components.CheckboxProps{ + ID: "disabled-checkbox", + Name: "disabled", + Value: "disabled", + Label: "Disabled option", + Attributes: templ.Attributes{"disabled": "true"}, + }) +
+
+

Disabled Checked Checkbox

+ @components.Checkbox(components.CheckboxProps{ + ID: "disabled-checked-checkbox", + Name: "disabled-checked", + Value: "disabled-checked", + Label: "Disabled checked option", + Attributes: templ.Attributes{"checked": "true", "disabled": "true"}, + }) +
+
+

Checkbox without Label

+ @components.Checkbox(components.CheckboxProps{ + ID: "no-label-checkbox", + Name: "no-label", + Value: "no-label", + }) +
+
+
+} + +================ +File: internals/ui/showcase/datepicker.templ +================ +package showcase + +import "github.com/axzilla/goilerplate/pkg/components" + +templ DatepickerShowcase() { +
+ @components.Datepicker(components.DatepickerProps{ + ID: "my-datepicker", + Name: "selected-date", + Placeholder: "Select a date", + Format: "YYYY-MM-DD", + Class: "w-full max-w-xs", + }) +
+} + +================ +File: internals/ui/showcase/dropdown_menu.templ +================ +package showcase + +import ( + "github.com/axzilla/goilerplate/pkg/components" + "github.com/axzilla/goilerplate/pkg/icons" +) + +templ DropdownMenuShowcase() { +
+
+ @components.DropdownMenu(components.DropdownMenuProps{ + Items: []components.DropdownMenuItem{ + {Label: "Profile", Value: "profile"}, + {Label: "Settings", Value: "settings"}, + {Label: "Logout", Value: "logout"}, + }, + }) + @components.DropdownMenu(components.DropdownMenuProps{ + Trigger: components.Button(components.ButtonProps{ + Text: "User Menu", + Variant: "outline", + IconLeft: icons.Menu(icons.IconProps{Size: "16"}), + }), + Position: "right", + Items: []components.DropdownMenuItem{ + { + Label: "Profile", + IconLeft: icons.User(icons.IconProps{Size: "16"}), + Href: "/docs/components/dropdown-menu", + }, + { + Label: "Settings", + IconLeft: icons.Settings(icons.IconProps{Size: "16"}), + Href: "/docs/components/dropdown-menu", + }, + { + Label: "Logout", + IconLeft: icons.LogOut(icons.IconProps{Size: "16"}), + Value: "logout", + }, + }, + }) + @components.DropdownMenu(components.DropdownMenuProps{ + Trigger: components.Button(components.ButtonProps{ + Text: "Advanced Menu", + Variant: "outline", + IconLeft: icons.Menu(icons.IconProps{Size: "16"}), + }), + Position: "left", + Items: []components.DropdownMenuItem{ + {Label: "File", SubItems: []components.DropdownMenuItem{ + {Label: "New", Value: "new", Attributes: templ.Attributes{"@click": "alert('New')"}}, + {Label: "Open", Value: "open", Attributes: templ.Attributes{"@click": "alert('Open')"}}, + {Label: "Save", Value: "save", Attributes: templ.Attributes{"@click": "alert('Save')"}}, + }}, + {Label: "Edit", SubItems: []components.DropdownMenuItem{ + {Label: "Cut", Value: "cut", Attributes: templ.Attributes{"@click": "alert('Cut')"}}, + {Label: "Copy", Value: "copy", Attributes: templ.Attributes{"@click": "alert('Copy')"}}, + {Label: "Paste", Value: "paste", Attributes: templ.Attributes{"@click": "alert('Paste')"}}, + }}, + {Label: "View", Disabled: true}, + {Label: "Help", Href: "https://github.com/axzilla/goilerplate", Target: "_blank"}, + }, + }) +
+
+} + +================ +File: internals/ui/showcase/embed.go +================ +package showcase + +import ( + "embed" +) + +//go:embed *.templ +var TemplFiles embed.FS + +================ +File: internals/ui/showcase/form.templ +================ +package showcase + +import ( + "encoding/json" + "github.com/axzilla/goilerplate/pkg/components" +) + +type SignupFormData struct { + Email string `json:"email"` + Role string `json:"role"` + NotificationTypes []string `json:"notificationTypes"` + Newsletter bool `json:"newsletter"` + Terms bool `json:"terms"` + Date string `json:"date"` +} + +func (d SignupFormData) ToJSON() string { + json, _ := json.Marshal(d) + return string(json) +} + +templ FormShowcase() { + @components.Form(components.FormProps[SignupFormData]{ + ID: "signup-form", + Name: "signup", + Action: "/api/signup", + InitialData: SignupFormData{ + Email: "", + Role: "admin", + NotificationTypes: []string{}, + Newsletter: true, + Terms: true, + }, + Debug: true, + }) { +

Account Settings

+ // Date +
+ + @components.Datepicker(components.DatepickerProps{ + ID: "my-datepicker", + Name: "selected-date", + Placeholder: "Select a date", + Format: "M d, Y", + Class: "w-full", + Attributes: templ.Attributes{"x-model": "formData.date"}, + }) +
+ // Email Input +
+ + @components.Input(components.InputProps{ + Type: "email", + Name: "email", + Placeholder: "Enter your email", + Attributes: templ.Attributes{"x-model": "formData.email"}, + }) +
+ // Role Select +
+ + @components.Select(components.SelectProps{ + ID: "role", + Name: "role", + Placeholder: "Select role", + Options: []components.SelectOption{ + {Label: "User", Value: "user"}, + {Label: "Admin", Value: "admin"}, + {Label: "Editor", Value: "editor"}, + }, + Attributes: templ.Attributes{"x-model": "formData.role"}, + }) +
+ // Notification Types (Multiple Checkboxes) +
+ +
+ @components.Checkbox(components.CheckboxProps{ + ID: "notify-email", + Name: "notificationTypes", + Value: "email", + Label: "Email Notifications", + Attributes: templ.Attributes{ + ":checked": "formData.notificationTypes.includes('email')", + "@click": `() => { + const i = formData.notificationTypes.indexOf('email'); + const n = formData.notificationTypes; + i > -1 ? n.splice(i, 1) : n.push('email'); + }`, + }, + }) + @components.Checkbox(components.CheckboxProps{ + ID: "notify-sms", + Name: "notificationTypes", + Value: "sms", + Label: "SMS Notifications", + Attributes: templ.Attributes{ + ":checked": "formData.notificationTypes.includes('sms')", + "@click": `() => { + const index = formData.notificationTypes.indexOf('sms'); + if (index > -1) { + formData.notificationTypes.splice(index, 1); + } else { + formData.notificationTypes.push('sms'); + } + }`, + }, + }) +
+
+ // Marketing Consent (Radio) +
+ + @components.RadioGroup(components.RadioGroupProps{Name: "contact-method"}) { + @components.RadioGroupItem(components.RadioGroupItemProps{ + Value: "all", + ID: "marketing-all", + Name: "marketing", + Label: templ.Raw("All marketing emails"), + Attributes: templ.Attributes{"x-model": "formData.marketingConsent"}, + }) + @components.RadioGroupItem(components.RadioGroupItemProps{ + Value: "selected", + ID: "marketing-selected", + Name: "marketing", + Label: templ.Raw("Only selected emails"), + Attributes: templ.Attributes{"x-model": "formData.marketingConsent"}, + }) + @components.RadioGroupItem(components.RadioGroupItemProps{ + Value: "none", + ID: "marketing-none", + Name: "marketing", + Label: templ.Raw("No marketing emails"), + Attributes: templ.Attributes{"x-model": "formData.marketingConsent"}, + }) + } +
+ // Newsletter Toggle +
+ @components.Toggle(components.ToggleProps{ + ID: "newsletter", + Name: "newsletter", + LabelRight: "Subscribe to newsletter", + Attributes: templ.Attributes{ + "x-model": "formData.newsletter", + }, + }) +
+ // Terms Checkbox +
+ @components.Checkbox(components.CheckboxProps{ + ID: "terms", + Name: "terms", + Label: "I accept the terms and conditions", + Attributes: templ.Attributes{"x-model": "formData.terms"}, + }) +
+ // Submit Button +
+ @components.Button(components.ButtonProps{ + Text: "Save Changes", + Attributes: templ.Attributes{ + "@click": "submit", + }, + }) +
+ } +} + +================ +File: internals/ui/showcase/icon.templ +================ +package showcase + +import "github.com/axzilla/goilerplate/pkg/icons" + +templ IconShowcase() { +
+
+
+

Basic Icons

+
+ @icons.User(icons.IconProps{Size: "24"}) + @icons.House(icons.IconProps{Size: "24"}) + @icons.Settings(icons.IconProps{Size: "24"}) +
+
+
+

Colored Icons

+
+ @icons.Heart(icons.IconProps{Size: "24", Color: "red"}) + @icons.Star(icons.IconProps{Size: "24", Color: "gold"}) + @icons.Check(icons.IconProps{Size: "24", Color: "green"}) +
+
+
+

Filled Icons

+
+ @icons.Circle(icons.IconProps{Size: "24", Fill: "blue", Stroke: "blue"}) + @icons.Square(icons.IconProps{Size: "24", Fill: "purple", Stroke: "purple"}) + @icons.Triangle(icons.IconProps{Size: "24", Fill: "orange", Stroke: "orange"}) +
+
+
+

Different Sizes

+
+ @icons.House(icons.IconProps{Size: "16"}) + @icons.House(icons.IconProps{Size: "24"}) + @icons.House(icons.IconProps{Size: "32"}) + @icons.House(icons.IconProps{Size: "48"}) +
+
+
+

Custom Classes

+
+ @icons.ArrowRight(icons.IconProps{Size: "24", Class: "text-blue-500 hover:text-blue-700"}) + @icons.ArrowLeft(icons.IconProps{Size: "24", Class: "text-green-500 hover:text-green-700"}) +
+
+
+
+} + +================ +File: internals/ui/showcase/input.templ +================ +package showcase + +import "github.com/axzilla/goilerplate/pkg/components" + +templ InputShowcase() { +
+
+
+

Default

+ @components.Input(components.InputProps{ + Type: "email", + }) +
+
+

With Placeholder

+ @components.Input(components.InputProps{ + Type: "email", + Placeholder: "e.g. john@doe.com", + }) +
+
+

File

+
+ @components.Input(components.InputProps{ + Type: "file", + }) +
+
+
+

Disabled

+ @components.Input(components.InputProps{ + Type: "email", + Attributes: templ.Attributes{"disabled": "true"}, + }) +
+
+

With Label

+
+ @components.Input(components.InputProps{ + ID: "email", + Type: "email", + Label: "Email", + }) +
+
+
+

With Description

+ @components.Input(components.InputProps{ + ID: "email", + Type: "email", + Description: "This is your accounts email address.", + }) +
+
+

With Error

+ @components.Input(components.InputProps{ + ID: "username", + Error: "Username must be more then 2 characters", + }) +
+
+

Advanced

+ @components.Input(components.InputProps{ + ID: "username", + Label: "Username", + Placeholder: "e.g. john123", + Description: "This is your public display name.", + Value: "", + Error: "Username must be more then 2 characters", + }) +
+
+
+} + +================ +File: internals/ui/showcase/modal.templ +================ +package showcase + +import "github.com/axzilla/goilerplate/pkg/components" + +templ ModalShowcase() { +
+
+ @components.ModalTrigger("default-modal") { + @components.Button(components.ButtonProps{Text: "Open Modal"}) + } + @components.Modal(components.ModalProps{ID: "default-modal", Class: "max-w-md"}) { + @components.ModalHeader() { + Are you absolutely sure? + } + @components.ModalBody() { + This action cannot be undone. This will permanently delete your account and remove your data from our servers. + } + @components.ModalFooter() { +
+ @components.ModalClose("default-modal") { + @components.Button(components.ButtonProps{ + Text: "Cancel", + }) + } + @components.ModalClose("default-modal") { + @components.Button(components.ButtonProps{ + Text: "Continue", + Variant: components.Secondary, + }) + } +
+ } + } +
+
+} + +================ +File: internals/ui/showcase/radio_group.templ +================ +package showcase + +import "github.com/axzilla/goilerplate/pkg/components" + +templ RadioGroupShowcase() { +
+ @components.RadioGroup(components.RadioGroupProps{}) { + @components.RadioGroupItem(components.RadioGroupItemProps{ + Value: "default", + ID: "r1", + Name: "view-mode", + Label: templ.Raw("Default"), + Attributes: templ.Attributes{"checked": true}, + }) + @components.RadioGroupItem(components.RadioGroupItemProps{ + Value: "comfortable", + ID: "r2", + Name: "view-mode", + Label: templ.Raw("Disabled"), + Attributes: templ.Attributes{"disabled": true}, + }) + @components.RadioGroupItem(components.RadioGroupItemProps{ + Value: "compact", + ID: "r3", + Name: "view-mode", + Label: templ.Raw("Compact"), + }) + } +
+} + +================ +File: internals/ui/showcase/select.templ +================ +package showcase + +import "github.com/axzilla/goilerplate/pkg/components" + +var xxx = "banana" + +templ SelectShowcase() { +
+
+
+

Default Select

+ @components.Select(components.SelectProps{ + ID: "fruit", + Name: "fruit", + Options: []components.SelectOption{ + {Label: "Apple", Value: "apple"}, + {Label: "Banana", Value: "banana"}, + {Label: "Orange", Value: "orange"}, + {Label: "Mango", Value: "mango"}, + }, + }) +
+
+

With Placeholder

+ @components.Select(components.SelectProps{ + ID: "fruit", + Name: "fruit", + Placeholder: "Select a fruit", + Options: []components.SelectOption{ + {Label: "Apple", Value: "apple"}, + {Label: "Banana", Value: "banana"}, + {Label: "Orange", Value: "orange"}, + {Label: "Mango", Value: "mango"}, + }, + }) +
+
+

Selected Value

+ @components.Select(components.SelectProps{ + ID: "selected", + Name: "selected", + Placeholder: "Select a fruit", + Options: []components.SelectOption{ + {Label: "Apple", Value: "apple"}, + {Label: "Banana", Value: "banana"}, + {Label: "Orange", Value: "orange", Attributes: templ.Attributes{"selected": true}}, + {Label: "Mango", Value: "mango"}, + }, + }) +
+
+

Disabled Select

+ @components.Select(components.SelectProps{ + ID: "disabled", + Name: "disabled", + Placeholder: "Select is disabled", + Attributes: templ.Attributes{":disabled": "true"}, + Options: []components.SelectOption{ + {Label: "Option 1", Value: "1"}, + {Label: "Option 2", Value: "2"}, + }, + }) +
+
+
+} + +================ +File: internals/ui/showcase/sheet.templ +================ +package showcase + +import "github.com/axzilla/goilerplate/pkg/components" + +var sides = []components.SheetSide{ + components.Left, + components.Top, + components.Right, + components.Bottom, +} + +templ SheetShowcase() { +
+
+ for _, side := range sides { + @components.SheetRoot() { + @components.Sheet(components.SheetProps{ + Side: side, + }) { +
+

Sheet Content

+

This is the main content of the sheet. You can put any components or text here.

+
+
+ @components.SheetClose("Close") +
+ } + @components.SheetTrigger(string(side), side) { + @components.Button(components.ButtonProps{Text: string(side)}) + } + } + } +
+
+} + +================ +File: internals/ui/showcase/tabs.templ +================ +package showcase + +import "github.com/axzilla/goilerplate/pkg/components" + +templ TabsShowcase() { +
+ @components.Tabs(components.TabsProps{ + Tabs: []components.Tab{ + { + ID: "account", + Title: "Account", + Content: AccountTab(), + }, + { + ID: "password", + Title: "Password", + Content: PasswordTab(), + }, + }, + TabsContainerClass: "w-full max-w-xs", + ContentContainerClass: "w-full max-w-xs", + }) +
+} + +templ AccountTab() { + @components.Card(components.CardProps{}) { + @components.CardHeader() { + @components.CardTitle() { + Account + } + @components.CardDescription() { + Make changes to your account here. Click save when you're done. + } + } + @components.CardContent() { +
+
+ + @components.Input(components.InputProps{ + Type: components.InputTypeText, + Placeholder: "Name", + ID: "name", + Value: "John Doe", + }) +
+
+ + @components.Input(components.InputProps{ + Type: components.InputTypeText, + Placeholder: "Username", + ID: "username", + Value: "@johndoe", + }) +
+
+ } + @components.CardFooter() { + @components.Button(components.ButtonProps{Text: "Save changes"}) + } + } +} + +templ PasswordTab() { + @components.Card(components.CardProps{}) { + @components.CardHeader() { + @components.CardTitle() { + Password + } + @components.CardDescription() { + Change your password here. After saving, you'll be logged out. + } + } + @components.CardContent() { +
+
+ + @components.Input(components.InputProps{ + Type: components.InputTypePassword, + Placeholder: "Current Password", + ID: "current_password", + }) +
+
+ + @components.Input(components.InputProps{ + Type: components.InputTypePassword, + Placeholder: "New Password", + ID: "new_password", + }) +
+
+ } + @components.CardFooter() { + @components.Button(components.ButtonProps{Text: "Save password"}) + } + } +} + +================ +File: internals/ui/showcase/toggle.templ +================ +package showcase + +import "github.com/axzilla/goilerplate/pkg/components" + +templ ToggleShowcase() { +
+
+
+

Without Label

+ @components.Toggle(components.ToggleProps{ + ID: "toggle", + Name: "toggle", + }) +
+
+

Label Placements

+
+ @components.Toggle(components.ToggleProps{ + ID: "toggle-right", + Name: "toggle-right", + LabelRight: "Label Right", + }) + @components.Toggle(components.ToggleProps{ + ID: "toggle-left", + Name: "toggle-left", + LabelLeft: "Label Left", + }) +
+
+
+

States

+
+ @components.Toggle(components.ToggleProps{ + ID: "toggle-checked", + Name: "toggle-checked", + LabelRight: "Checked Toggle", + Attributes: templ.Attributes{"x-bind:checked": "true"}, + }) + @components.Toggle(components.ToggleProps{ + ID: "toggle-disabled", + Name: "toggle-disabled", + LabelRight: "Disabled Toggle", + Attributes: templ.Attributes{"disabled": "true"}, + }) + @components.Toggle(components.ToggleProps{ + ID: "toggle-disabled-checked", + Name: "toggle-disabled-checked", + LabelRight: "Disabled Checked Toggle", + Attributes: templ.Attributes{"checked": "true", "disabled": true}, + }) +
+
+
+
+} + +================ +File: pkg/components/accordion.templ +================ +package components + +import ( + "github.com/axzilla/goilerplate/pkg/icons" + "github.com/axzilla/goilerplate/pkg/utils" +) + +// AccordionItem represents a single item in the Accordion component. +type AccordionItem struct { + // ID is the unique identifier for the accordion item. + // It is used to manage the open/closed state of the item. + ID string + + // Trigger is the content of the accordion item's header/trigger. + // This is typically text, but can be any templ.Component. + Trigger templ.Component + + // Content is the expandable content of the accordion item. + // This can be any templ.Component. + Content templ.Component +} + +// AccordionProps defines the properties for the Accordion component. +type AccordionProps struct { + // Items is a slice of AccordionItem structs representing each item in the accordion. + Items []AccordionItem + + // Class specifies additional CSS classes to apply to the accordion container. + // Default: "" (empty string) + Class string + + // Attributes allows passing additional HTML attributes to the accordion container element. + // Default: nil + Attributes templ.Attributes +} + +// Accordion renders an accordion component based on the provided props. +// It uses Alpine.js for interactivity and state management. +// +// Usage: +// +// @components.Accordion(components.AccordionProps{ +// Items: []components.AccordionItem{ +// { +// ID: "item-1", +// Trigger: templ.Raw("Is it accessible?"), +// Content: templ.Raw("Yes. It adheres to the WAI-ARIA design pattern."), +// }, +// { +// ID: "item-2", +// Trigger: templ.Raw("Is it styled?"), +// Content: templ.Raw("Yes. It comes with default styles that match the other components' aesthetic."), +// }, +// }, +// Class: "w-full sm:max-w-[70%]", +// Attributes: templ.Attributes{"data-testid": "my-accordion"}, +// }) +// +// Props: +// - Items: A slice of AccordionItem structs, each representing an item in the accordion. +// - Class: Additional CSS classes to apply to the accordion container. Default: "" (empty string) +// - Attributes: Additional HTML attributes to apply to the accordion container element. Default: nil +templ Accordion(props AccordionProps) { +
+ for _, item := range props.Items { +
+

+ +

+
+ @item.Content +
+
+ } +
+} + +================ +File: pkg/components/alert.templ +================ +package components + +import "github.com/axzilla/goilerplate/pkg/utils" + +// AlertVariant represents the visual style of the alert. +type AlertVariant string + +// Constants for alert variants. +const ( + DefaultAlert AlertVariant = "default" + DestructiveAlert AlertVariant = "destructive" +) + +// AlertProps defines the properties for the Alert component. +type AlertProps struct { + // Variant determines the visual style of the alert. + // Default: DefaultAlert + Variant AlertVariant + // Class specifies additional CSS classes to apply to the alert. + // Default: "" (empty string) + Class string +} + +// getAlertVariantClasses returns the CSS classes for the given alert variant. +func getAlertVariantClasses(variant AlertVariant) string { + switch variant { + case DestructiveAlert: + return "border-destructive text-destructive" + default: + return "border-border text-foreground" + } +} + +// Alert renders an alert component based on the provided props and children. +// It can be customized with two visual styles: Default and Destructive. +// All content, including icons, should be passed in as children. +// +// Usage: +// +// @components.Alert(components.AlertProps{Variant: components.DestructiveAlert}) { +// @components.ExclamationTriangleIcon() +// @components.AlertTitle{"Error"} +// @components.AlertDescription{"Your session has expired. Please log in again."} +// } +// +// Props: +// - Variant: The visual style of the alert (DefaultAlert or DestructiveAlert). Default: DefaultAlert +// - Class: Additional CSS classes to apply to the alert. Default: "" (empty string) +templ Alert(props AlertProps) { +
svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg+div]:translate-y-[-3px] [&:has(svg)]:pl-11", + getAlertVariantClasses(props.Variant), + props.Class, + ), + } + role="alert" + > + { children... } +
+} + +// AlertTitle renders the title of the alert. +templ AlertTitle() { +
+ { children... } +
+} + +// AlertDescription renders the description of the alert. +templ AlertDescription() { +
+ { children... } +
+} + +================ +File: pkg/components/avatar.templ +================ +package components + +import ( + "fmt" + "github.com/axzilla/goilerplate/pkg/utils" + "strings" +) + +// AvatarSize represents the size of the avatar. +type AvatarSize string + +const ( + AvatarSizeSmall AvatarSize = "small" + AvatarSizeMedium AvatarSize = "medium" + AvatarSizeLarge AvatarSize = "large" +) + +// AvatarProps defines the properties for the Avatar component. +type AvatarProps struct { + // ImageSrc is the URL of the avatar image. + // If empty, initials will be used. + ImageSrc string + + // Name is used to generate initials if ImageSrc is empty. + Name string + + // Size determines the size of the avatar. + // Default: AvatarSizeMedium + Size AvatarSize + + // Class specifies additional CSS classes to apply to the avatar. + Class string + + // Attributes allows passing additional HTML attributes to the avatar element. + Attributes templ.Attributes +} + +// getInitials generates initials from the given name. +func AvatarInitials(name string) string { + parts := strings.Fields(name) + initials := "" + for i, part := range parts { + if i > 1 { + break + } + if len(part) > 0 { + initials += string(part[0]) + } + } + return strings.ToUpper(initials) +} + +// getSizeClasses returns the CSS classes for the given avatar size. +func AvatarSizeClasses(size AvatarSize) string { + switch size { + case AvatarSizeSmall: + return "w-8 h-8 text-xs" + case AvatarSizeLarge: + return "w-16 h-16 text-xl" + default: + return "w-12 h-12 text-base" + } +} + +// Avatar renders an avatar component based on the provided props. +// It displays an image if ImageSrc is provided, otherwise it shows initials. +// +// Usage: +// +// @components.Avatar(components.AvatarProps{ +// ImageSrc: "https://example.com/avatar.jpg", +// Name: "John Doe", +// Size: components.AvatarSizeMedium, +// Class: "border-2 border-blue-500", +// }) +// +// Props: +// - ImageSrc: The URL of the avatar image. Default: "" (empty string) +// - Name: The name used to generate initials if ImageSrc is empty. Default: "" (empty string) +// - Size: The size of the avatar (AvatarSizeSmall, AvatarSizeMedium, AvatarSizeLarge). Default: AvatarSizeMedium +// - Class: Additional CSS classes to apply to the avatar. Default: "" (empty string) +// - Attributes: Additional HTML attributes to apply to the avatar element. Default: nil +templ Avatar(props AvatarProps) { +
+ if props.ImageSrc != "" { + { + } else { + + { AvatarInitials(props.Name) } + + } +
+} + +================ +File: pkg/components/button.templ +================ +package components + +import ( + "github.com/axzilla/goilerplate/pkg/utils" + "strings" +) + +// ButtonVariant represents the visual style of the button. +type ButtonVariant string + +// ButtonSize represents the size of the button. +type ButtonSize string + +// Constants for button variants and sizes. +const ( + Default ButtonVariant = "default" + Destructive ButtonVariant = "destructive" + Outline ButtonVariant = "outline" + Secondary ButtonVariant = "secondary" + Ghost ButtonVariant = "ghost" + Link ButtonVariant = "link" + + Md ButtonSize = "md" + Sm ButtonSize = "sm" + Lg ButtonSize = "lg" + ButtonIcon ButtonSize = "icon" +) + +// Button defines the properties for the Button component. +type ButtonProps struct { + // Class specifies additional CSS classes to apply to the button. + // Default: "" (empty string) + Class string + + // Text is the content of the button. + // Default: "" (empty string) + Text string + + // Variant determines the visual style of the button. + // Default: Default + Variant ButtonVariant + + // Size sets the size of the button. + // Default: Md + Size ButtonSize + + // FullWidth determines whether the button should take up the full width of its container. + // Default: false + FullWidth bool + + // Href, if provided, renders the button as an anchor tag with this URL. + // Default: "" (empty string) + Href string + + // Target specifies the target attribute for the anchor tag (only used when Href is provided). + // Default: "" (empty string) + Target string + + // Disabled can be either a bool or a string. + // If bool (Go), it directly controls the disabled state. + // If string, it's treated as a JavaScript expression for dynamic disabling. + Disabled any + + // Type specifies the type of the button. Default: "button" + // Default: "" (empty string) + Type string + + // Attributes allows passing additional HTML attributes to the button or anchor element. + // Default: nil + Attributes templ.Attributes + + // IconLeft specifies an icon component to be displayed on the left side of the button text. + // Default: nil + IconLeft templ.Component + + // IconRight specifies an icon component to be displayed on the right side of the button text. + // Default: nil + IconRight templ.Component +} + +// Variant als Methode +func (b ButtonProps) variantClasses() string { + switch b.Variant { + case Destructive: + return "bg-destructive text-destructive-foreground hover:bg-destructive/90" + case Outline: + return "border border-input bg-background hover:bg-accent hover:text-accent-foreground" + case Secondary: + return "bg-secondary text-secondary-foreground hover:bg-secondary/80" + case Ghost: + return "hover:bg-accent hover:text-accent-foreground" + case Link: + return "text-primary underline-offset-4 hover:underline" + default: + return "bg-primary text-primary-foreground hover:bg-primary/90" + } +} + +// Size als Methode +func (b ButtonProps) sizeClasses() string { + switch b.Size { + case Sm: + return "h-9 px-3 rounded-md" + case Lg: + return "h-11 px-8 rounded-md" + case ButtonIcon: + return "h-10 w-10" + default: + return "h-10 px-4 py-2 rounded-md" + } +} + +func (b ButtonProps) modifierClasses() string { + classes := []string{} + if b.FullWidth { + classes = append(classes, "w-full") + } + return strings.Join(classes, " ") +} + +// Button renders a button or anchor component based on the provided props. +// It can be customized with various visual styles, sizes, and behaviors. +// +// Usage: +// +// @components.Button(components.ButtonProps{ +// Text: "Click me", +// Variant: components.Primary, +// Size: components.Md, +// FullWidth: false, +// IconLeft: components.Icon(components.IconProps{Name: "user"}), +// IconRight: components.Icon(components.IconProps{Name: "arrow-right"}), +// Attributes: templ.Attributes{ +// "aria-label": "Click this button", +// "data-testid": "main-button", +// }, +// }) +// +// Props: +// - Class: Additional CSS classes to apply to the button. Default: "" (empty string) +// - Text: The text content of the button. Default: "" (empty string) +// - Variant: The visual style of the button (e.g., Default, Destructive, Outline). Default: Default +// - Size: The size of the button (Md, Sm, Lg, Icon). Default: Md +// - FullWidth: Whether the button should take up the full width of its container. Default: false +// - Href: If provided, renders the button as an anchor tag with this URL. Default: "" (empty string) +// - Target: The target attribute for the anchor tag (only used when Href is provided). Default: "" (empty string) +// - Disabled: Can be either a bool or a string. If bool (Go), it directly controls the disabled state. If string, it's treated as a JavaScript expression for dynamic disabling. Default: nil +// - Type: The type of the button. Default: "button" +// - Attributes: Additional HTML attributes to apply to the button or anchor element. Default: nil +// - IconLeft: An icon component to be displayed on the left side of the button text. Default: nil +// - IconRight: An icon component to be displayed on the right side of the button text. Default: nil +templ Button(props ButtonProps) { + if props.Href != "" { + + { children... } + @renderButtonContent(props) + + } else { + + } +} + +// renderButtonContent renders the content of the button, including icons and text +templ renderButtonContent(props ButtonProps) { + + if props.IconLeft != nil { + @props.IconLeft + } + { props.Text } + if props.IconRight != nil { + @props.IconRight + } + +} + +================ +File: pkg/components/card.templ +================ +package components + +import "github.com/axzilla/goilerplate/pkg/utils" + +// CardProps defines the properties for the Card component. +type CardProps struct { + // Class specifies additional CSS classes to apply to the card. + // Default: "" (empty string) + Class string + + // Attributes allows passing additional HTML attributes to the card element. + // Default: nil + Attributes templ.Attributes +} + +// Card renders a card component based on the provided props. +// It can be customized with additional classes and attributes. +// +// Usage: +// +// @components.Card(components.CardProps{ +// Class: "custom-card", +// Attributes: templ.Attributes{"data-testid": "my-card"}, +// }) { +// // Card content goes here +// } +// +// Props: +// - Class: Additional CSS classes to apply to the card. Default: "" (empty string) +// - Attributes: Additional HTML attributes to apply to the card element. Default: nil +templ Card(props CardProps) { +
+ { children... } +
+} + +// CardHeader renders the header section of a card. +// +// Usage: +// +// @components.CardHeader() { +// @components.CardTitle() { Card Title } +// @components.CardDescription() { Card description goes here } +// } +templ CardHeader() { +
+ { children... } +
+} + +// CardTitle renders the title of a card. +// +// Usage: +// +// @components.CardTitle() { +// My Card Title +// } +templ CardTitle() { +

+ { children... } +

+} + +// CardDescription renders the description of a card. +// +// Usage: +// +// @components.CardDescription() { +// This is a detailed description of the card's content. +// } +templ CardDescription() { +

+ { children... } +

+} + +// CardContent renders the main content section of a card. +// +// Usage: +// +// @components.CardContent() { +// // Main card content goes here +// } +templ CardContent() { +
+ { children... } +
+} + +// CardFooter renders the footer section of a card. +// +// Usage: +// +// @components.CardFooter() { +// @components.Button(components.ButtonProps{Text: "Submit"}) +// } +templ CardFooter() { +
+ { children... } +
+} + +================ +File: pkg/components/checkbox.templ +================ +package components + +import "github.com/axzilla/goilerplate/pkg/utils" +import "github.com/axzilla/goilerplate/pkg/icons" + +// CheckboxProps defines the properties for the Checkbox component. +type CheckboxProps struct { + // ID is the unique identifier for the checkbox input. + ID string + + // Name is the name attribute for the checkbox input. + Name string + + // Value is the value attribute for the checkbox input. + Value string + + // Label is the text label associated with the checkbox. + // If empty, no label will be rendered. + Label string + + // Class specifies additional CSS classes for the container + Class string + + // Attributes allows passing additional HTML attributes + Attributes templ.Attributes +} + +// Checkbox renders a customizable checkbox component with an associated label. +// +// Props: +// - ID: The unique identifier for the checkbox input. Required. +// - Name: The name attribute for the checkbox input. Required. +// - Value: The value attribute for the checkbox input. Required. +// - Label: The text label associated with the checkbox. Optional. +// - Class: Additional CSS classes to apply to the checkbox container. Optional. +// - Attributes: Additional HTML attributes to apply to the checkbox input element. Optional. +// CheckboxProps bleibt gleich, nur die Template-Implementierung ändert sich +templ Checkbox(props CheckboxProps) { + +} + +================ +File: pkg/components/datepicker.templ +================ +package components + +import ( + "github.com/axzilla/goilerplate/pkg/icons" + "github.com/axzilla/goilerplate/pkg/utils" +) + +// DatepickerProps defines the properties for the Datepicker component. +type DatepickerProps struct { + // ID is the unique identifier for the datepicker input. + ID string + + // Name is the name attribute for the datepicker input. + Name string + + // Placeholder is the placeholder text for the datepicker input. + Placeholder string + + // Format specifies the date format to use. Options: "M d, Y", "MM-DD-YYYY", "DD-MM-YYYY", "YYYY-MM-DD", "D d M, Y" + // Default: "M d, Y" + Format string + + // Class specifies additional CSS classes to apply to the datepicker container. + Class string + + // Attributes allows passing additional HTML attributes to the datepicker input element. + Attributes templ.Attributes +} + +// Datepicker renders an enhanced datepicker component with an input field and a calendar view. +// It uses Alpine.js for interactivity and provides various formatting options and improved navigation. +// This version supports dark mode using Tailwind CSS variables. +// +// Usage: +// +// @components.Datepicker(components.DatepickerProps{ +// ID: "my-datepicker", +// Name: "selected-date", +// Placeholder: "Select a date", +// Format: "YYYY-MM-DD", +// Class: "w-full", +// }) +// +// Props: +// - ID: The unique identifier for the datepicker input. Default: "" (empty string) +// - Name: The name attribute for the datepicker input. Default: "" (empty string) +// - Placeholder: The placeholder text for the datepicker input. Default: "" (empty string) +// - Format: The date format to use. Default: "M d, Y" +// - Class: Additional CSS classes to apply to the datepicker container. Default: "" (empty string) +// - Attributes: Additional HTML attributes to apply to the datepicker input element. Default: nil +templ Datepicker(props DatepickerProps) { +
+
+ +
+ @icons.Calendar(icons.IconProps{}) +
+
+
+
+
+ + +
+
+ + +
+
+
+ +
+
+ + +
+
+
+} + +================ +File: pkg/components/dropdown_menu.templ +================ +package components + +import ( + "fmt" + "github.com/axzilla/goilerplate/pkg/icons" + "github.com/axzilla/goilerplate/pkg/utils" + "strings" +) + +// DropdownMenuItem represents an item in the dropdown menu +type DropdownMenuItem struct { + Label string // The text to display for the menu item + Value string // The value associated with the menu item (for non-link items) + Href string // The URL to navigate to if the item is a link + Target string // The target attribute for link items (e.g., "_blank" for new tab) + IconLeft templ.Component // An optional icon component to display on the left side of the item + IconRight templ.Component // An optional icon component to display on the right side of the item + SubItems []DropdownMenuItem // A slice of DropdownMenuItems for nested submenus + Disabled bool // Whether the item is disabled or not + // Attributes allows passing additional HTML attributes to the accordion container element. + // Default: nil + Attributes templ.Attributes +} + +// DropdownMenuProps defines the properties for the DropdownMenu component +type DropdownMenuProps struct { + Items []DropdownMenuItem // The list of items to display in the dropdown menu + Trigger templ.Component // An optional custom trigger component (default is a button if not provided) + Class string // Additional CSS classes to apply to the root element + Position string // The preferred position of the dropdown ("left", "right", "top", or "bottom") +} + +func (d DropdownMenuItem) ModifierClasses() string { + classes := []string{} + if d.Disabled { + classes = append(classes, "text-muted-foreground cursor-not-allowed") + } else { + classes = append(classes, "text-foreground hover:bg-accent hover:text-accent-foreground") + } + return strings.Join(classes, " ") +} + +// renderMenuItem is a helper function to render a single menu item +// It handles rendering of regular items, links, and submenus recursively +templ renderMenuItem(item DropdownMenuItem, index int, depth int) { + if len(item.SubItems) > 0 { +
+ + if depth < 3 { + + } +
+ } else if item.Href != "" { + + + if item.IconLeft != nil { + @item.IconLeft + } + { item.Label } + + if item.IconRight != nil { + + @item.IconRight + + } + + } else { + + } +} + +// DropdownMenu renders an enhanced dropdown menu component +// It can be customized with various styles, positions, and behaviors. +// +// Usage: +// +// @components.DropdownMenu(components.DropdownMenuProps{ +// Trigger: components.Button(components.ButtonProps{ +// Text: "Open Menu", +// IconRight: components.Icon(components.IconProps{Name: "chevron-down"}), +// }), +// Position: "bottom", +// Items: []components.DropdownMenuItem{ +// {Label: "Option 1", Value: "opt1"}, +// {Label: "Option 2", Value: "opt2", IconLeft: components.Icon(components.IconProps{Name: "settings"})}, +// {Label: "Submenu", SubItems: []components.DropdownMenuItem{ +// {Label: "Sub Option 1", Value: "sub1"}, +// {Label: "Sub Option 2", Value: "sub2"}, +// }}, +// }, +// }) +// +// Props: +// - Items: Slice of DropdownMenuItem, defining the content of the dropdown +// - Trigger: Custom component to trigger the dropdown (optional, default is a basic button) +// - Class: Additional CSS classes to apply to the root element +// - Position: Preferred position of the dropdown ("left", "right", "top", or "bottom") +// - Attributes: Additional HTML attributes to apply to the accordion container element. Default: nil +// +// Features: +// - Supports nested submenus up to 3 levels deep +// - Automatically adjusts position based on available space +// - Supports custom icons for menu items +// - Handles disabled states for menu items +// - Uses Tailwind CSS for styling, including dark mode support +// - Implements keyboard navigation and ARIA attributes for accessibility +templ DropdownMenu(props DropdownMenuProps) { +
+
+ if props.Trigger != nil { + @props.Trigger + } else { + @Button(ButtonProps{ + Text: "Options", + Variant: "outline", + IconRight: icons.ChevronDown(icons.IconProps{Size: "16"}), + }) + } +
+ +
+} + +================ +File: pkg/components/embed.go +================ +package components + +import "embed" + +//go:embed *.templ +var TemplFiles embed.FS + +================ +File: pkg/components/footer.templ +================ +package components + +import "time" +import "fmt" + +templ Footer() { +
+
+

+ { fmt.Sprintf("© %d goilerplate.", time.Now().Year()) } Stupid code not excluded. +

+
+
+} + +================ +File: pkg/components/form.templ +================ +package components + +import "fmt" + +// Basis Interface für Form Daten +type FormDataProvider interface { + // Muss JSON-serialisierbar sein + ToJSON() string +} + +// FormProps definiert die Basis-Konfiguration der Form +type FormProps[T FormDataProvider] struct { + // Core configuration + ID string + Name string + Class string + + // Form handling + Action string + Method string + + // Initial form data + InitialData T + + // Debug mode + Debug bool + + // Additional attributes + Attributes templ.Attributes +} + +// Form Component +templ Form[T FormDataProvider](props FormProps[T]) { +
+
+ { children... } + if props.Debug { + @FormDebug() + } +
+} + +// Form Debug Component +templ FormDebug() { +
+
+

Form Debug

+ +
+
+
+

Form Data:

+

+			
+
+

Errors:

+

+			
+
+

State:

+
+
Submitting:
+
Submitted:
+
+
+
+
+} + +================ +File: pkg/components/input.templ +================ +package components + +import "github.com/axzilla/goilerplate/pkg/utils" + +// InputType represents the type of the input field. +type InputType string + +// Constants for input types. +const ( + InputTypeText InputType = "text" + InputTypePassword InputType = "password" + InputTypeEmail InputType = "email" + InputTypeNumber InputType = "number" + InputTypeTel InputType = "tel" + InputTypeURL InputType = "url" + InputTypeSearch InputType = "search" + InputTypeDate InputType = "date" + InputTypeTime InputType = "time" + InputTypeFile InputType = "file" +) + +// InputProps defines the properties for the Input component. +type InputProps struct { + // Type specifies the type of the input field. + // Default: Text + Type InputType + + // Placeholder is the placeholder text for the input field. + // Default: "" (empty string) + Placeholder string + + // Value is the current value of the input field. + // Default: "" (empty string) + Value string + + // Name is the name attribute of the input field. + // Default: "" (empty string) + Name string + + // ID is the unique identifier for the input field. + // Default: "" (empty string) + ID string + + // Label + Label string + + // Description + Description string + + // Error + Error string + + // Class specifies additional CSS classes to apply to the input field. + // Default: "" (empty string) + Class string + + // FileAccept specifies which file types are accepted (only for file type). + // Default: "" (empty string) + FileAccept string + + // Attributes allows passing additional HTML attributes to the input element. + // Default: nil + Attributes templ.Attributes +} + +// Input renders an input component based on the provided props. +// It can be customized with various types, sizes, and behaviors. +// +// Usage: +// +// @components.Input(components.InputProps{ +// Type: components.Email, +// Placeholder: "Enter your email", +// ID: "email-input", +// Class: "custom-input", +// Attributes: templ.Attributes{ +// "aria-label": "Email input", +// "data-testid": "email-input", +// }, +// }) +// +// Props: +// - Type: The type of the input field (e.g., Text, Email, Password). Default: Text +// - Placeholder: The placeholder text for the input field. Default: "" (empty string) +// - Value: The current value of the input field. Default: "" (empty string) +// - Name: The name attribute of the input field. Default: "" (empty string) +// - ID: The unique identifier for the input field. Default: "" (empty string) +// - Class: Additional CSS classes to apply to the input field. Default: "" (empty string) +// - Disabled: Can be either a bool or a string. If bool (Go), it directly controls the disabled state. If string, it's treated as a JavaScript expression for dynamic disabling. Default: nil +// - FileAccept: Specifies which file types are accepted (only for file type). Default: "" (empty string) +// - Attributes: Additional HTML attributes to apply to the input element. Default: nil +templ Input(props InputProps) { + + if props.Label != "" { + + } + + if props.Description != "" { +

{ props.Description }

+ } + if props.Error != "" { +

{ props.Error }

+ } +
+} + +================ +File: pkg/components/modal.templ +================ +package components + +import "github.com/axzilla/goilerplate/pkg/utils" + +// ModalProps defines the properties for the Modal component. +type ModalProps struct { + // ID is a unique identifier for the modal. + // It's used to control opening and closing. + // This should be unique across your application. + ID string + + // Class specifies additional CSS classes to apply to the modal container. + Class string +} + +// Modal renders a modal dialog component. +// It uses Alpine.js for state management and animations. +// +// Usage: +// +// @components.ModalTrigger("default-modal") { +// @components.Button(components.ButtonProps{Text: "Open Modal"}) +// } +// +// @components.Modal(components.ModalProps{ID: "default-modal", Class: "max-w-md"}) { +// @components.ModalHeader() { +// Are you absolutely sure? +// } +// @components.ModalBody() { +// This action cannot be undone. This will permanently delete your account and remove your data from our servers. +// } +// @components.ModalFooter() { +//
+// @components.ModalClose("default-modal") { +// @components.Button(components.ButtonProps{ +// Text: "Cancel", +// }) +// } +// @components.ModalClose("default-modal") { +// @components.Button(components.ButtonProps{ +// Text: "Continue", +// Variant: components.Secondary, +// }) +// } +//
+// } +// } +// +// The Modal component should be used in conjunction with ModalTrigger to open it. +templ Modal(props ModalProps) { + +} + +// ModalTrigger renders an element that opens the modal when clicked. +// +// Usage: +// +// @components.ModalTrigger("example-modal") { +// @components.Button(components.ButtonProps{Text: "Open Modal"}) +// } +// +// The 'id' parameter should match the ID of the Modal you want to open. +templ ModalTrigger(id string) { + + { children... } + +} + +// ModalClose renders an element that closes the modal when clicked. +// +// Usage: +// +// @components.ModalClose("example-modal") { +// @components.Button(components.ButtonProps{ +// Text: "Close", +// Variant: components.Secondary, +// }) +// } +// +// The 'id' parameter should match the ID of the Modal you want to close. +templ ModalClose(id string) { + + { children... } + +} + +// ModalHeader renders the header section of the modal. +// +// Usage: +// +// @components.ModalHeader() { +// Modal Title +// @components.ModalClose("example-modal") +// } +templ ModalHeader() { +
+ +
+} + +// ModalBody renders the main content area of the modal. +// +// Usage: +// +// @components.ModalBody() { +//

This is the modal content.

+// } +templ ModalBody() { +
+ { children... } +
+} + +// ModalFooter renders the footer section of the modal, typically containing action buttons. +// +// Usage: +// +// @components.ModalFooter() { +// @components.ModalClose("example-modal") { +// @components.Button(components.ButtonProps{ +// Text: "Close", +// Variant: components.Secondary, +// }) +// } +// } +templ ModalFooter() { +
+ { children... } +
+} + +================ +File: pkg/components/navbar.templ +================ +package components + +import ( + "github.com/axzilla/goilerplate/internals/shared" + "github.com/axzilla/goilerplate/pkg/icons" +) + +templ Navbar() { + +} + +templ NavbarMobileMenu() { + @SheetRoot() { + @Sheet(SheetProps{Side: Left}) { + for _, section := range shared.Sections { +
+

{ section.Title }

+ +
+ } + } + @SheetTrigger(string(Left), Left) { + + } + } +} + +================ +File: pkg/components/radio_group.templ +================ +package components + +import "github.com/axzilla/goilerplate/pkg/utils" + +// RadioGroupProps defines the properties for the RadioGroup component. +type RadioGroupProps struct { + // Name is the name attribute for the radio group + Name string + // Class specifies additional CSS classes + Class string + // Attributes allows passing additional HTML attributes + Attributes templ.Attributes +} + +// RadioGroupItemProps defines the properties for a single radio button item. +type RadioGroupItemProps struct { + // Value is the value attribute for the radio button + Value string + // Name is the name attribute, should match the RadioGroup's name + Name string + // ID is the unique identifier for the radio button + ID string + // Label is the text label displayed next to the radio button + Label templ.Component + // Class specifies additional CSS classes + Class string + // Attributes allows passing additional HTML attributes + Attributes templ.Attributes +} + +// RadioGroup renders a group of radio buttons with shared name attribute. +// +// Usage: +// +// @components.RadioGroup(components.RadioGroupProps{ +// Name: "marketing", +// }) { +// @components.RadioGroupItem(components.RadioGroupItemProps{ +// Value: "email", +// Name: "marketing", +// ID: "marketing-email", +// Label: templ.Raw("Email Marketing"), +// }) +// } +templ RadioGroup(props RadioGroupProps) { +
+ { children... } +
+} + +// RadioGroupItem renders a single radio button with an integrated label. +// +// Usage: +// +// @components.RadioGroupItem(components.RadioGroupItemProps{ +// Value: "email", +// Name: "marketing", +// ID: "marketing-email", +// Label: templ.Raw("Email Marketing"), +// Attributes: templ.Attributes{"checked": selectedOption == "email"}, +// }) +templ RadioGroupItem(props RadioGroupItemProps) { + +} + +================ +File: pkg/components/select.templ +================ +// pkg/components/select.templ + +package components + +import ( + "github.com/axzilla/goilerplate/pkg/icons" +) + +// SelectProps defines the properties for the Select component. +type SelectProps struct { + // ID is the unique identifier for the select input + ID string + + // Name is the name attribute for the select input + Name string + + // Placeholder text when no option is selected + Placeholder string + + // Options is the array of available options + Options []SelectOption + + // Class specifies additional CSS classes + Class string + + // Attributes allows passing additional HTML attributes + Attributes templ.Attributes +} + +// SelectOption represents an option in the select menu +type SelectOption struct { + // Label is the text shown to the user + Label string + + // Value is the actual value of the option + Value string + + // Attributes allows passing additional HTML attributes + Attributes templ.Attributes +} + +// Select renders a custom select component with a button trigger and dropdown menu. +// It supports keyboard navigation, disabled states, and custom styling. +// +// Usage: +// +// @components.Select(components.SelectProps{ +// ID: "fruit", +// Name: "fruit", +// Placeholder: "Select a fruit", +// Value: "'apple'", +// Options: []components.SelectOption{ +// {Label: "Apple", Value: "apple"}, +// {Label: "Banana", Value: "banana", Disabled: true}, +// }, +// }) +// +// Props: +// - ID: The unique identifier for the select input. Required. +// - Name: The name attribute for the select input. Required. +// - Placeholder: Text shown when no option is selected. Optional. +// - Options: Array of SelectOption defining the available choices. Required. +// - Value: The selected value. Can be a string or JS expression. Optional. +// - Disabled: Controls the disabled state. Can be a string or JS expression. Optional. +// - Class: Additional CSS classes. Optional. +// - Attributes: Additional HTML attributes. Optional. +templ Select(props SelectProps) { +
+ +
+ @icons.ChevronDown(icons.IconProps{Size: "16", Class: "text-muted-foreground"}) +
+
+} + +================ +File: pkg/components/sheet.templ +================ +package components + +// SheetSide represents the side from which the sheet will appear. +type SheetSide string + +// Constants for sheet sides. +const ( + Top SheetSide = "top" + Right SheetSide = "right" + Bottom SheetSide = "bottom" + Left SheetSide = "left" +) + +// SheetProps defines the properties for the Sheet component. +type SheetProps struct { + // Title is the heading text for the sheet. + // Default: "" (empty string) + Title string + + // Description is the subheading or description text for the sheet. + // Default: "" (empty string) + Description string + + // Side determines from which side the sheet will appear. + // Default: Right + Side SheetSide +} + +// SheetRoot renders the root component for the Sheet, setting up the Alpine.js data and event handlers. +// +// Usage: +// +// @components.SheetRoot() { +// // Sheet trigger and content go here +// } +templ SheetRoot() { +
+ { children... } +
+} + +// Sheet renders the main sheet component with backdrop and content. +// +// Usage: +// +// @components.Sheet(components.SheetProps{ +// Title: "Sheet Title", +// Description: "Sheet description goes here", +// Side: components.Right, +// }) { +// // Sheet content goes here +// } +// +// Props: +// - Title: The heading text for the sheet. Default: "" (empty string) +// - Description: The subheading or description text for the sheet. Default: "" (empty string) +// - Side: Determines from which side the sheet will appear. Default: Right +templ Sheet(props SheetProps) { + +
+ +
+
+
+

{ props.Title }

+

{ props.Description }

+
+
+ { children... } +
+
+
+} + +// SheetTrigger renders a trigger element that opens the sheet when clicked. +// +// Usage: +// +// @components.SheetTrigger("Open Sheet", components.Right) { +// +// } +// +// Props: +// - text: The text content of the trigger (unused in the current implementation) +// - side: The side from which the sheet should appear +templ SheetTrigger(text string, side SheetSide) { + + { children... } + +} + +// SheetClose renders a button that closes the sheet when clicked. +// +// Usage: +// +// @components.SheetClose("Close") +// +// Props: +// - text: The text content of the close button +templ SheetClose(text string) { + +} + +================ +File: pkg/components/sidebar_right.templ +================ +package components + +import "github.com/axzilla/goilerplate/pkg/icons" + +type SidebarRightLItem struct { + ImageSrc string + Url string + Text string +} + +var SidebarRightLinks = []SidebarRightLItem{ + { + ImageSrc: "https://templ.guide/img/logo.svg", + Url: "https://templ.guide", + Text: "Elevate your Go projects with type-safe, efficient HTML templating.", + }, + { + ImageSrc: "https://alpinejs.dev/alpine_long.svg", + Url: "https://alpinejs.dev", + Text: "Simplify your JavaScript with a lightweight, powerful framework.", + }, + { + ImageSrc: "https://tailwindcss.com/_next/static/media/tailwindcss-logotype-white.944c5d0ef628083bb316f9b3d643385c86bcdb3d.svg", + Url: "https://tailwindcss.com", + Text: "Create beautiful, responsive designs with ease.", + }, +} + +templ SidebarRight() { + +} + +================ +File: pkg/components/sidebar.templ +================ +package components + +import "github.com/axzilla/goilerplate/internals/shared" + +templ Sidebar() { + +} + +================ +File: pkg/components/tabs.templ +================ +package components + +// Tab represents a single tab in the Tabs component. +type Tab struct { + // ID is the unique identifier for the tab. + ID string + + // Title is the text displayed on the tab button. + Title string + + // Content is the templ.Component to be rendered when the tab is active. + Content templ.Component +} + +// TabsProps defines the properties for the Tabs component. +type TabsProps struct { + // Tabs is an array of Tab structs representing each tab in the component. + Tabs []Tab + + // TabsContainerClass specifies additional CSS classes for the tabs container. + // Default: "" (empty string) + TabsContainerClass string + + // ContentContainerClass specifies additional CSS classes for the content container. + // Default: "" (empty string) + ContentContainerClass string +} + +// Tabs renders a tabbed interface component based on the provided props. +// It uses Alpine.js for interactivity and state management. +// +// Usage: +// +// @components.Tabs(components.TabsProps{ +// Tabs: []components.Tab{ +// {ID: "1", Title: "Tab 1", Content: Tab1Content()}, +// {ID: "2", Title: "Tab 2", Content: Tab2Content()}, +// }, +// TabsContainerClass: "w-full max-w-md", +// ContentContainerClass: "mt-4", +// }) +// +// Props: +// - Tabs: An array of Tab structs, each representing a tab in the interface. +// - TabsContainerClass: Additional CSS classes for the tabs container. Default: "" (empty string) +// - ContentContainerClass: Additional CSS classes for the content container. Default: "" (empty string) +templ Tabs(props TabsProps) { +
+ +
+ + for _, tab := range props.Tabs { + + } + +
+
+
+
+ +
+ + for _, tab := range props.Tabs { +
+ @tab.Content +
+ } +
+
+} + +================ +File: pkg/components/themeswitcher.templ +================ +package components + +import "github.com/axzilla/goilerplate/pkg/icons" + +templ ThemeSwitcher() { + @Button(ButtonProps{ + Size: ButtonIcon, + Variant: Ghost, + IconLeft: templ.Component(DynamicThemeIcon()), + Attributes: templ.Attributes{ + "@click": "toggleTheme()", + }, + }) +} + +templ DynamicThemeIcon() { + + @LightIcon() + + + @DarkIcon() + +} + +templ DarkIcon() { + @icons.Moon(icons.IconProps{}) +} + +templ LightIcon() { + @icons.SunMedium(icons.IconProps{}) +} + +================ +File: pkg/components/toggle.templ +================ +package components + +// ToggleSize represents the size of the toggle +type ToggleSize string + +// ToggleLabelPlacement represents where the label should be placed +type ToggleLabelPlacement string + +// ToggleProps defines the properties for the Toggle component +type ToggleProps struct { + // ID is the unique identifier for the toggle input + ID string + + // Name is the name attribute for the toggle input + Name string + + // Label is the text label for the toggle + LabelLeft string + + // Label is the text label for the toggle + LabelRight string + + // Class specifies additional CSS classes + Class string + + // Attributes allows passing additional HTML attributes + Attributes templ.Attributes +} + +// Toggle renders a toggle switch component based on the provided props. +// It can be customized with different label placements, and supports +// both static and dynamic states through Alpine.js integration. +// +// Props: +// - ID: The unique identifier for the toggle input. Required. +// - Name: The name attribute for the toggle input. Required. +// - LabelLeft: The text label for the toggle. Optional. +// - LabelRight: The text label for the toggle. Optional. +// - Class: Additional CSS classes. Optional. +// - Attributes: Additional HTML attributes. Optional. +templ Toggle(props ToggleProps) { + +} + +================ +File: pkg/icons/embed.go +================ +package icons + +import "embed" + +//go:embed icons.go +var TemplFiles embed.FS + +================ +File: pkg/icons/icon_defs.go +================ +package icons +// This file is auto generated +var AArrowDown = Icon("a-arrow-down") +var AArrowUp = Icon("a-arrow-up") +var ALargeSmall = Icon("a-large-small") +var Accessibility = Icon("accessibility") +var Activity = Icon("activity") +var AirVent = Icon("air-vent") +var Airplay = Icon("airplay") +var AlarmClockCheck = Icon("alarm-clock-check") +var AlarmClockMinus = Icon("alarm-clock-minus") +var AlarmClockOff = Icon("alarm-clock-off") +var AlarmClockPlus = Icon("alarm-clock-plus") +var AlarmClock = Icon("alarm-clock") +var AlarmSmoke = Icon("alarm-smoke") +var Album = Icon("album") +var AlignCenterHorizontal = Icon("align-center-horizontal") +var AlignCenterVertical = Icon("align-center-vertical") +var AlignCenter = Icon("align-center") +var AlignEndHorizontal = Icon("align-end-horizontal") +var AlignEndVertical = Icon("align-end-vertical") +var AlignHorizontalDistributeCenter = Icon("align-horizontal-distribute-center") +var AlignHorizontalDistributeEnd = Icon("align-horizontal-distribute-end") +var AlignHorizontalDistributeStart = Icon("align-horizontal-distribute-start") +var AlignHorizontalJustifyCenter = Icon("align-horizontal-justify-center") +var AlignHorizontalJustifyEnd = Icon("align-horizontal-justify-end") +var AlignHorizontalJustifyStart = Icon("align-horizontal-justify-start") +var AlignHorizontalSpaceAround = Icon("align-horizontal-space-around") +var AlignHorizontalSpaceBetween = Icon("align-horizontal-space-between") +var AlignJustify = Icon("align-justify") +var AlignLeft = Icon("align-left") +var AlignRight = Icon("align-right") +var AlignStartHorizontal = Icon("align-start-horizontal") +var AlignStartVertical = Icon("align-start-vertical") +var AlignVerticalDistributeCenter = Icon("align-vertical-distribute-center") +var AlignVerticalDistributeEnd = Icon("align-vertical-distribute-end") +var AlignVerticalDistributeStart = Icon("align-vertical-distribute-start") +var AlignVerticalJustifyCenter = Icon("align-vertical-justify-center") +var AlignVerticalJustifyEnd = Icon("align-vertical-justify-end") +var AlignVerticalJustifyStart = Icon("align-vertical-justify-start") +var AlignVerticalSpaceAround = Icon("align-vertical-space-around") +var AlignVerticalSpaceBetween = Icon("align-vertical-space-between") +var Ambulance = Icon("ambulance") +var Ampersand = Icon("ampersand") +var Ampersands = Icon("ampersands") +var Amphora = Icon("amphora") +var Anchor = Icon("anchor") +var Angry = Icon("angry") +var Annoyed = Icon("annoyed") +var Antenna = Icon("antenna") +var Anvil = Icon("anvil") +var Aperture = Icon("aperture") +var AppWindowMac = Icon("app-window-mac") +var AppWindow = Icon("app-window") +var Apple = Icon("apple") +var ArchiveRestore = Icon("archive-restore") +var ArchiveX = Icon("archive-x") +var Archive = Icon("archive") +var Armchair = Icon("armchair") +var ArrowBigDownDash = Icon("arrow-big-down-dash") +var ArrowBigDown = Icon("arrow-big-down") +var ArrowBigLeftDash = Icon("arrow-big-left-dash") +var ArrowBigLeft = Icon("arrow-big-left") +var ArrowBigRightDash = Icon("arrow-big-right-dash") +var ArrowBigRight = Icon("arrow-big-right") +var ArrowBigUpDash = Icon("arrow-big-up-dash") +var ArrowBigUp = Icon("arrow-big-up") +var ArrowDown01 = Icon("arrow-down-0-1") +var ArrowDown10 = Icon("arrow-down-1-0") +var ArrowDownAZ = Icon("arrow-down-a-z") +var ArrowDownFromLine = Icon("arrow-down-from-line") +var ArrowDownLeft = Icon("arrow-down-left") +var ArrowDownNarrowWide = Icon("arrow-down-narrow-wide") +var ArrowDownRight = Icon("arrow-down-right") +var ArrowDownToDot = Icon("arrow-down-to-dot") +var ArrowDownToLine = Icon("arrow-down-to-line") +var ArrowDownUp = Icon("arrow-down-up") +var ArrowDownWideNarrow = Icon("arrow-down-wide-narrow") +var ArrowDownZA = Icon("arrow-down-z-a") +var ArrowDown = Icon("arrow-down") +var ArrowLeftFromLine = Icon("arrow-left-from-line") +var ArrowLeftRight = Icon("arrow-left-right") +var ArrowLeftToLine = Icon("arrow-left-to-line") +var ArrowLeft = Icon("arrow-left") +var ArrowRightFromLine = Icon("arrow-right-from-line") +var ArrowRightLeft = Icon("arrow-right-left") +var ArrowRightToLine = Icon("arrow-right-to-line") +var ArrowRight = Icon("arrow-right") +var ArrowUp01 = Icon("arrow-up-0-1") +var ArrowUp10 = Icon("arrow-up-1-0") +var ArrowUpAZ = Icon("arrow-up-a-z") +var ArrowUpDown = Icon("arrow-up-down") +var ArrowUpFromDot = Icon("arrow-up-from-dot") +var ArrowUpFromLine = Icon("arrow-up-from-line") +var ArrowUpLeft = Icon("arrow-up-left") +var ArrowUpNarrowWide = Icon("arrow-up-narrow-wide") +var ArrowUpRight = Icon("arrow-up-right") +var ArrowUpToLine = Icon("arrow-up-to-line") +var ArrowUpWideNarrow = Icon("arrow-up-wide-narrow") +var ArrowUpZA = Icon("arrow-up-z-a") +var ArrowUp = Icon("arrow-up") +var ArrowsUpFromLine = Icon("arrows-up-from-line") +var Asterisk = Icon("asterisk") +var AtSign = Icon("at-sign") +var Atom = Icon("atom") +var AudioLines = Icon("audio-lines") +var AudioWaveform = Icon("audio-waveform") +var Award = Icon("award") +var Axe = Icon("axe") +var Axis3d = Icon("axis-3d") +var Baby = Icon("baby") +var Backpack = Icon("backpack") +var BadgeAlert = Icon("badge-alert") +var BadgeCent = Icon("badge-cent") +var BadgeCheck = Icon("badge-check") +var BadgeDollarSign = Icon("badge-dollar-sign") +var BadgeEuro = Icon("badge-euro") +var BadgeHelp = Icon("badge-help") +var BadgeIndianRupee = Icon("badge-indian-rupee") +var BadgeInfo = Icon("badge-info") +var BadgeJapaneseYen = Icon("badge-japanese-yen") +var BadgeMinus = Icon("badge-minus") +var BadgePercent = Icon("badge-percent") +var BadgePlus = Icon("badge-plus") +var BadgePoundSterling = Icon("badge-pound-sterling") +var BadgeRussianRuble = Icon("badge-russian-ruble") +var BadgeSwissFranc = Icon("badge-swiss-franc") +var BadgeX = Icon("badge-x") +var Badge = Icon("badge") +var BaggageClaim = Icon("baggage-claim") +var Ban = Icon("ban") +var Banana = Icon("banana") +var Bandage = Icon("bandage") +var Banknote = Icon("banknote") +var Barcode = Icon("barcode") +var Baseline = Icon("baseline") +var Bath = Icon("bath") +var BatteryCharging = Icon("battery-charging") +var BatteryFull = Icon("battery-full") +var BatteryLow = Icon("battery-low") +var BatteryMedium = Icon("battery-medium") +var BatteryWarning = Icon("battery-warning") +var Battery = Icon("battery") +var Beaker = Icon("beaker") +var BeanOff = Icon("bean-off") +var Bean = Icon("bean") +var BedDouble = Icon("bed-double") +var BedSingle = Icon("bed-single") +var Bed = Icon("bed") +var Beef = Icon("beef") +var BeerOff = Icon("beer-off") +var Beer = Icon("beer") +var BellDot = Icon("bell-dot") +var BellElectric = Icon("bell-electric") +var BellMinus = Icon("bell-minus") +var BellOff = Icon("bell-off") +var BellPlus = Icon("bell-plus") +var BellRing = Icon("bell-ring") +var Bell = Icon("bell") +var BetweenHorizontalEnd = Icon("between-horizontal-end") +var BetweenHorizontalStart = Icon("between-horizontal-start") +var BetweenVerticalEnd = Icon("between-vertical-end") +var BetweenVerticalStart = Icon("between-vertical-start") +var BicepsFlexed = Icon("biceps-flexed") +var Bike = Icon("bike") +var Binary = Icon("binary") +var Binoculars = Icon("binoculars") +var Biohazard = Icon("biohazard") +var Bird = Icon("bird") +var Bitcoin = Icon("bitcoin") +var Blend = Icon("blend") +var Blinds = Icon("blinds") +var Blocks = Icon("blocks") +var BluetoothConnected = Icon("bluetooth-connected") +var BluetoothOff = Icon("bluetooth-off") +var BluetoothSearching = Icon("bluetooth-searching") +var Bluetooth = Icon("bluetooth") +var Bold = Icon("bold") +var Bolt = Icon("bolt") +var Bomb = Icon("bomb") +var Bone = Icon("bone") +var BookA = Icon("book-a") +var BookAudio = Icon("book-audio") +var BookCheck = Icon("book-check") +var BookCopy = Icon("book-copy") +var BookDashed = Icon("book-dashed") +var BookDown = Icon("book-down") +var BookHeadphones = Icon("book-headphones") +var BookHeart = Icon("book-heart") +var BookImage = Icon("book-image") +var BookKey = Icon("book-key") +var BookLock = Icon("book-lock") +var BookMarked = Icon("book-marked") +var BookMinus = Icon("book-minus") +var BookOpenCheck = Icon("book-open-check") +var BookOpenText = Icon("book-open-text") +var BookOpen = Icon("book-open") +var BookPlus = Icon("book-plus") +var BookText = Icon("book-text") +var BookType = Icon("book-type") +var BookUp2 = Icon("book-up-2") +var BookUp = Icon("book-up") +var BookUser = Icon("book-user") +var BookX = Icon("book-x") +var Book = Icon("book") +var BookmarkCheck = Icon("bookmark-check") +var BookmarkMinus = Icon("bookmark-minus") +var BookmarkPlus = Icon("bookmark-plus") +var BookmarkX = Icon("bookmark-x") +var Bookmark = Icon("bookmark") +var BoomBox = Icon("boom-box") +var BotMessageSquare = Icon("bot-message-square") +var BotOff = Icon("bot-off") +var Bot = Icon("bot") +var Box = Icon("box") +var Boxes = Icon("boxes") +var Braces = Icon("braces") +var Brackets = Icon("brackets") +var BrainCircuit = Icon("brain-circuit") +var BrainCog = Icon("brain-cog") +var Brain = Icon("brain") +var BrickWall = Icon("brick-wall") +var BriefcaseBusiness = Icon("briefcase-business") +var BriefcaseConveyorBelt = Icon("briefcase-conveyor-belt") +var BriefcaseMedical = Icon("briefcase-medical") +var Briefcase = Icon("briefcase") +var BringToFront = Icon("bring-to-front") +var Brush = Icon("brush") +var BugOff = Icon("bug-off") +var BugPlay = Icon("bug-play") +var Bug = Icon("bug") +var Building2 = Icon("building-2") +var Building = Icon("building") +var BusFront = Icon("bus-front") +var Bus = Icon("bus") +var CableCar = Icon("cable-car") +var Cable = Icon("cable") +var CakeSlice = Icon("cake-slice") +var Cake = Icon("cake") +var Calculator = Icon("calculator") +var CalendarArrowDown = Icon("calendar-arrow-down") +var CalendarArrowUp = Icon("calendar-arrow-up") +var CalendarCheck2 = Icon("calendar-check-2") +var CalendarCheck = Icon("calendar-check") +var CalendarClock = Icon("calendar-clock") +var CalendarCog = Icon("calendar-cog") +var CalendarDays = Icon("calendar-days") +var CalendarFold = Icon("calendar-fold") +var CalendarHeart = Icon("calendar-heart") +var CalendarMinus2 = Icon("calendar-minus-2") +var CalendarMinus = Icon("calendar-minus") +var CalendarOff = Icon("calendar-off") +var CalendarPlus2 = Icon("calendar-plus-2") +var CalendarPlus = Icon("calendar-plus") +var CalendarRange = Icon("calendar-range") +var CalendarSearch = Icon("calendar-search") +var CalendarX2 = Icon("calendar-x-2") +var CalendarX = Icon("calendar-x") +var Calendar = Icon("calendar") +var CameraOff = Icon("camera-off") +var Camera = Icon("camera") +var CandyCane = Icon("candy-cane") +var CandyOff = Icon("candy-off") +var Candy = Icon("candy") +var Cannabis = Icon("cannabis") +var CaptionsOff = Icon("captions-off") +var Captions = Icon("captions") +var CarFront = Icon("car-front") +var CarTaxiFront = Icon("car-taxi-front") +var Car = Icon("car") +var Caravan = Icon("caravan") +var Carrot = Icon("carrot") +var CaseLower = Icon("case-lower") +var CaseSensitive = Icon("case-sensitive") +var CaseUpper = Icon("case-upper") +var CassetteTape = Icon("cassette-tape") +var Cast = Icon("cast") +var Castle = Icon("castle") +var Cat = Icon("cat") +var Cctv = Icon("cctv") +var ChartArea = Icon("chart-area") +var ChartBarBig = Icon("chart-bar-big") +var ChartBarDecreasing = Icon("chart-bar-decreasing") +var ChartBarIncreasing = Icon("chart-bar-increasing") +var ChartBarStacked = Icon("chart-bar-stacked") +var ChartBar = Icon("chart-bar") +var ChartCandlestick = Icon("chart-candlestick") +var ChartColumnBig = Icon("chart-column-big") +var ChartColumnDecreasing = Icon("chart-column-decreasing") +var ChartColumnIncreasing = Icon("chart-column-increasing") +var ChartColumnStacked = Icon("chart-column-stacked") +var ChartColumn = Icon("chart-column") +var ChartGantt = Icon("chart-gantt") +var ChartLine = Icon("chart-line") +var ChartNetwork = Icon("chart-network") +var ChartNoAxesColumnDecreasing = Icon("chart-no-axes-column-decreasing") +var ChartNoAxesColumnIncreasing = Icon("chart-no-axes-column-increasing") +var ChartNoAxesColumn = Icon("chart-no-axes-column") +var ChartNoAxesCombined = Icon("chart-no-axes-combined") +var ChartNoAxesGantt = Icon("chart-no-axes-gantt") +var ChartPie = Icon("chart-pie") +var ChartScatter = Icon("chart-scatter") +var ChartSpline = Icon("chart-spline") +var CheckCheck = Icon("check-check") +var Check = Icon("check") +var ChefHat = Icon("chef-hat") +var Cherry = Icon("cherry") +var ChevronDown = Icon("chevron-down") +var ChevronFirst = Icon("chevron-first") +var ChevronLast = Icon("chevron-last") +var ChevronLeft = Icon("chevron-left") +var ChevronRight = Icon("chevron-right") +var ChevronUp = Icon("chevron-up") +var ChevronsDownUp = Icon("chevrons-down-up") +var ChevronsDown = Icon("chevrons-down") +var ChevronsLeftRightEllipsis = Icon("chevrons-left-right-ellipsis") +var ChevronsLeftRight = Icon("chevrons-left-right") +var ChevronsLeft = Icon("chevrons-left") +var ChevronsRightLeft = Icon("chevrons-right-left") +var ChevronsRight = Icon("chevrons-right") +var ChevronsUpDown = Icon("chevrons-up-down") +var ChevronsUp = Icon("chevrons-up") +var Chrome = Icon("chrome") +var Church = Icon("church") +var CigaretteOff = Icon("cigarette-off") +var Cigarette = Icon("cigarette") +var CircleAlert = Icon("circle-alert") +var CircleArrowDown = Icon("circle-arrow-down") +var CircleArrowLeft = Icon("circle-arrow-left") +var CircleArrowOutDownLeft = Icon("circle-arrow-out-down-left") +var CircleArrowOutDownRight = Icon("circle-arrow-out-down-right") +var CircleArrowOutUpLeft = Icon("circle-arrow-out-up-left") +var CircleArrowOutUpRight = Icon("circle-arrow-out-up-right") +var CircleArrowRight = Icon("circle-arrow-right") +var CircleArrowUp = Icon("circle-arrow-up") +var CircleCheckBig = Icon("circle-check-big") +var CircleCheck = Icon("circle-check") +var CircleChevronDown = Icon("circle-chevron-down") +var CircleChevronLeft = Icon("circle-chevron-left") +var CircleChevronRight = Icon("circle-chevron-right") +var CircleChevronUp = Icon("circle-chevron-up") +var CircleDashed = Icon("circle-dashed") +var CircleDivide = Icon("circle-divide") +var CircleDollarSign = Icon("circle-dollar-sign") +var CircleDotDashed = Icon("circle-dot-dashed") +var CircleDot = Icon("circle-dot") +var CircleEllipsis = Icon("circle-ellipsis") +var CircleEqual = Icon("circle-equal") +var CircleFadingArrowUp = Icon("circle-fading-arrow-up") +var CircleFadingPlus = Icon("circle-fading-plus") +var CircleGauge = Icon("circle-gauge") +var CircleHelp = Icon("circle-help") +var CircleMinus = Icon("circle-minus") +var CircleOff = Icon("circle-off") +var CircleParkingOff = Icon("circle-parking-off") +var CircleParking = Icon("circle-parking") +var CirclePause = Icon("circle-pause") +var CirclePercent = Icon("circle-percent") +var CirclePlay = Icon("circle-play") +var CirclePlus = Icon("circle-plus") +var CirclePower = Icon("circle-power") +var CircleSlash2 = Icon("circle-slash-2") +var CircleSlash = Icon("circle-slash") +var CircleStop = Icon("circle-stop") +var CircleUserRound = Icon("circle-user-round") +var CircleUser = Icon("circle-user") +var CircleX = Icon("circle-x") +var Circle = Icon("circle") +var CircuitBoard = Icon("circuit-board") +var Citrus = Icon("citrus") +var Clapperboard = Icon("clapperboard") +var ClipboardCheck = Icon("clipboard-check") +var ClipboardCopy = Icon("clipboard-copy") +var ClipboardList = Icon("clipboard-list") +var ClipboardMinus = Icon("clipboard-minus") +var ClipboardPaste = Icon("clipboard-paste") +var ClipboardPenLine = Icon("clipboard-pen-line") +var ClipboardPen = Icon("clipboard-pen") +var ClipboardPlus = Icon("clipboard-plus") +var ClipboardType = Icon("clipboard-type") +var ClipboardX = Icon("clipboard-x") +var Clipboard = Icon("clipboard") +var Clock1 = Icon("clock-1") +var Clock10 = Icon("clock-10") +var Clock11 = Icon("clock-11") +var Clock12 = Icon("clock-12") +var Clock2 = Icon("clock-2") +var Clock3 = Icon("clock-3") +var Clock4 = Icon("clock-4") +var Clock5 = Icon("clock-5") +var Clock6 = Icon("clock-6") +var Clock7 = Icon("clock-7") +var Clock8 = Icon("clock-8") +var Clock9 = Icon("clock-9") +var ClockAlert = Icon("clock-alert") +var ClockArrowDown = Icon("clock-arrow-down") +var ClockArrowUp = Icon("clock-arrow-up") +var Clock = Icon("clock") +var CloudCog = Icon("cloud-cog") +var CloudDownload = Icon("cloud-download") +var CloudDrizzle = Icon("cloud-drizzle") +var CloudFog = Icon("cloud-fog") +var CloudHail = Icon("cloud-hail") +var CloudLightning = Icon("cloud-lightning") +var CloudMoonRain = Icon("cloud-moon-rain") +var CloudMoon = Icon("cloud-moon") +var CloudOff = Icon("cloud-off") +var CloudRainWind = Icon("cloud-rain-wind") +var CloudRain = Icon("cloud-rain") +var CloudSnow = Icon("cloud-snow") +var CloudSunRain = Icon("cloud-sun-rain") +var CloudSun = Icon("cloud-sun") +var CloudUpload = Icon("cloud-upload") +var Cloud = Icon("cloud") +var Cloudy = Icon("cloudy") +var Clover = Icon("clover") +var Club = Icon("club") +var CodeXml = Icon("code-xml") +var Code = Icon("code") +var Codepen = Icon("codepen") +var Codesandbox = Icon("codesandbox") +var Coffee = Icon("coffee") +var Cog = Icon("cog") +var Coins = Icon("coins") +var Columns2 = Icon("columns-2") +var Columns3 = Icon("columns-3") +var Columns4 = Icon("columns-4") +var Combine = Icon("combine") +var Command = Icon("command") +var Compass = Icon("compass") +var Component = Icon("component") +var Computer = Icon("computer") +var ConciergeBell = Icon("concierge-bell") +var Cone = Icon("cone") +var Construction = Icon("construction") +var ContactRound = Icon("contact-round") +var Contact = Icon("contact") +var Container = Icon("container") +var Contrast = Icon("contrast") +var Cookie = Icon("cookie") +var CookingPot = Icon("cooking-pot") +var CopyCheck = Icon("copy-check") +var CopyMinus = Icon("copy-minus") +var CopyPlus = Icon("copy-plus") +var CopySlash = Icon("copy-slash") +var CopyX = Icon("copy-x") +var Copy = Icon("copy") +var Copyleft = Icon("copyleft") +var Copyright = Icon("copyright") +var CornerDownLeft = Icon("corner-down-left") +var CornerDownRight = Icon("corner-down-right") +var CornerLeftDown = Icon("corner-left-down") +var CornerLeftUp = Icon("corner-left-up") +var CornerRightDown = Icon("corner-right-down") +var CornerRightUp = Icon("corner-right-up") +var CornerUpLeft = Icon("corner-up-left") +var CornerUpRight = Icon("corner-up-right") +var Cpu = Icon("cpu") +var CreativeCommons = Icon("creative-commons") +var CreditCard = Icon("credit-card") +var Croissant = Icon("croissant") +var Crop = Icon("crop") +var Cross = Icon("cross") +var Crosshair = Icon("crosshair") +var Crown = Icon("crown") +var Cuboid = Icon("cuboid") +var CupSoda = Icon("cup-soda") +var Currency = Icon("currency") +var Cylinder = Icon("cylinder") +var Dam = Icon("dam") +var DatabaseBackup = Icon("database-backup") +var DatabaseZap = Icon("database-zap") +var Database = Icon("database") +var Delete = Icon("delete") +var Dessert = Icon("dessert") +var Diameter = Icon("diameter") +var DiamondMinus = Icon("diamond-minus") +var DiamondPercent = Icon("diamond-percent") +var DiamondPlus = Icon("diamond-plus") +var Diamond = Icon("diamond") +var Dice1 = Icon("dice-1") +var Dice2 = Icon("dice-2") +var Dice3 = Icon("dice-3") +var Dice4 = Icon("dice-4") +var Dice5 = Icon("dice-5") +var Dice6 = Icon("dice-6") +var Dices = Icon("dices") +var Diff = Icon("diff") +var Disc2 = Icon("disc-2") +var Disc3 = Icon("disc-3") +var DiscAlbum = Icon("disc-album") +var Disc = Icon("disc") +var Divide = Icon("divide") +var DnaOff = Icon("dna-off") +var Dna = Icon("dna") +var Dock = Icon("dock") +var Dog = Icon("dog") +var DollarSign = Icon("dollar-sign") +var Donut = Icon("donut") +var DoorClosed = Icon("door-closed") +var DoorOpen = Icon("door-open") +var Dot = Icon("dot") +var Download = Icon("download") +var DraftingCompass = Icon("drafting-compass") +var Drama = Icon("drama") +var Dribbble = Icon("dribbble") +var Drill = Icon("drill") +var Droplet = Icon("droplet") +var Droplets = Icon("droplets") +var Drum = Icon("drum") +var Drumstick = Icon("drumstick") +var Dumbbell = Icon("dumbbell") +var EarOff = Icon("ear-off") +var Ear = Icon("ear") +var EarthLock = Icon("earth-lock") +var Earth = Icon("earth") +var Eclipse = Icon("eclipse") +var EggFried = Icon("egg-fried") +var EggOff = Icon("egg-off") +var Egg = Icon("egg") +var EllipsisVertical = Icon("ellipsis-vertical") +var Ellipsis = Icon("ellipsis") +var EqualNot = Icon("equal-not") +var Equal = Icon("equal") +var Eraser = Icon("eraser") +var EthernetPort = Icon("ethernet-port") +var Euro = Icon("euro") +var Expand = Icon("expand") +var ExternalLink = Icon("external-link") +var EyeClosed = Icon("eye-closed") +var EyeOff = Icon("eye-off") +var Eye = Icon("eye") +var Facebook = Icon("facebook") +var Factory = Icon("factory") +var Fan = Icon("fan") +var FastForward = Icon("fast-forward") +var Feather = Icon("feather") +var Fence = Icon("fence") +var FerrisWheel = Icon("ferris-wheel") +var Figma = Icon("figma") +var FileArchive = Icon("file-archive") +var FileAudio2 = Icon("file-audio-2") +var FileAudio = Icon("file-audio") +var FileAxis3d = Icon("file-axis-3d") +var FileBadge2 = Icon("file-badge-2") +var FileBadge = Icon("file-badge") +var FileBox = Icon("file-box") +var FileChartColumnIncreasing = Icon("file-chart-column-increasing") +var FileChartColumn = Icon("file-chart-column") +var FileChartLine = Icon("file-chart-line") +var FileChartPie = Icon("file-chart-pie") +var FileCheck2 = Icon("file-check-2") +var FileCheck = Icon("file-check") +var FileClock = Icon("file-clock") +var FileCode2 = Icon("file-code-2") +var FileCode = Icon("file-code") +var FileCog = Icon("file-cog") +var FileDiff = Icon("file-diff") +var FileDigit = Icon("file-digit") +var FileDown = Icon("file-down") +var FileHeart = Icon("file-heart") +var FileImage = Icon("file-image") +var FileInput = Icon("file-input") +var FileJson2 = Icon("file-json-2") +var FileJson = Icon("file-json") +var FileKey2 = Icon("file-key-2") +var FileKey = Icon("file-key") +var FileLock2 = Icon("file-lock-2") +var FileLock = Icon("file-lock") +var FileMinus2 = Icon("file-minus-2") +var FileMinus = Icon("file-minus") +var FileMusic = Icon("file-music") +var FileOutput = Icon("file-output") +var FilePenLine = Icon("file-pen-line") +var FilePen = Icon("file-pen") +var FilePlus2 = Icon("file-plus-2") +var FilePlus = Icon("file-plus") +var FileQuestion = Icon("file-question") +var FileScan = Icon("file-scan") +var FileSearch2 = Icon("file-search-2") +var FileSearch = Icon("file-search") +var FileSliders = Icon("file-sliders") +var FileSpreadsheet = Icon("file-spreadsheet") +var FileStack = Icon("file-stack") +var FileSymlink = Icon("file-symlink") +var FileTerminal = Icon("file-terminal") +var FileText = Icon("file-text") +var FileType2 = Icon("file-type-2") +var FileType = Icon("file-type") +var FileUp = Icon("file-up") +var FileUser = Icon("file-user") +var FileVideo2 = Icon("file-video-2") +var FileVideo = Icon("file-video") +var FileVolume2 = Icon("file-volume-2") +var FileVolume = Icon("file-volume") +var FileWarning = Icon("file-warning") +var FileX2 = Icon("file-x-2") +var FileX = Icon("file-x") +var File = Icon("file") +var Files = Icon("files") +var Film = Icon("film") +var FilterX = Icon("filter-x") +var Filter = Icon("filter") +var Fingerprint = Icon("fingerprint") +var FireExtinguisher = Icon("fire-extinguisher") +var FishOff = Icon("fish-off") +var FishSymbol = Icon("fish-symbol") +var Fish = Icon("fish") +var FlagOff = Icon("flag-off") +var FlagTriangleLeft = Icon("flag-triangle-left") +var FlagTriangleRight = Icon("flag-triangle-right") +var Flag = Icon("flag") +var FlameKindling = Icon("flame-kindling") +var Flame = Icon("flame") +var FlashlightOff = Icon("flashlight-off") +var Flashlight = Icon("flashlight") +var FlaskConicalOff = Icon("flask-conical-off") +var FlaskConical = Icon("flask-conical") +var FlaskRound = Icon("flask-round") +var FlipHorizontal2 = Icon("flip-horizontal-2") +var FlipHorizontal = Icon("flip-horizontal") +var FlipVertical2 = Icon("flip-vertical-2") +var FlipVertical = Icon("flip-vertical") +var Flower2 = Icon("flower-2") +var Flower = Icon("flower") +var Focus = Icon("focus") +var FoldHorizontal = Icon("fold-horizontal") +var FoldVertical = Icon("fold-vertical") +var FolderArchive = Icon("folder-archive") +var FolderCheck = Icon("folder-check") +var FolderClock = Icon("folder-clock") +var FolderClosed = Icon("folder-closed") +var FolderCode = Icon("folder-code") +var FolderCog = Icon("folder-cog") +var FolderDot = Icon("folder-dot") +var FolderDown = Icon("folder-down") +var FolderGit2 = Icon("folder-git-2") +var FolderGit = Icon("folder-git") +var FolderHeart = Icon("folder-heart") +var FolderInput = Icon("folder-input") +var FolderKanban = Icon("folder-kanban") +var FolderKey = Icon("folder-key") +var FolderLock = Icon("folder-lock") +var FolderMinus = Icon("folder-minus") +var FolderOpenDot = Icon("folder-open-dot") +var FolderOpen = Icon("folder-open") +var FolderOutput = Icon("folder-output") +var FolderPen = Icon("folder-pen") +var FolderPlus = Icon("folder-plus") +var FolderRoot = Icon("folder-root") +var FolderSearch2 = Icon("folder-search-2") +var FolderSearch = Icon("folder-search") +var FolderSymlink = Icon("folder-symlink") +var FolderSync = Icon("folder-sync") +var FolderTree = Icon("folder-tree") +var FolderUp = Icon("folder-up") +var FolderX = Icon("folder-x") +var Folder = Icon("folder") +var Folders = Icon("folders") +var Footprints = Icon("footprints") +var Forklift = Icon("forklift") +var Forward = Icon("forward") +var Frame = Icon("frame") +var Framer = Icon("framer") +var Frown = Icon("frown") +var Fuel = Icon("fuel") +var Fullscreen = Icon("fullscreen") +var GalleryHorizontalEnd = Icon("gallery-horizontal-end") +var GalleryHorizontal = Icon("gallery-horizontal") +var GalleryThumbnails = Icon("gallery-thumbnails") +var GalleryVerticalEnd = Icon("gallery-vertical-end") +var GalleryVertical = Icon("gallery-vertical") +var Gamepad2 = Icon("gamepad-2") +var Gamepad = Icon("gamepad") +var Gauge = Icon("gauge") +var Gavel = Icon("gavel") +var Gem = Icon("gem") +var Ghost = Icon("ghost") +var Gift = Icon("gift") +var GitBranchPlus = Icon("git-branch-plus") +var GitBranch = Icon("git-branch") +var GitCommitHorizontal = Icon("git-commit-horizontal") +var GitCommitVertical = Icon("git-commit-vertical") +var GitCompareArrows = Icon("git-compare-arrows") +var GitCompare = Icon("git-compare") +var GitFork = Icon("git-fork") +var GitGraph = Icon("git-graph") +var GitMerge = Icon("git-merge") +var GitPullRequestArrow = Icon("git-pull-request-arrow") +var GitPullRequestClosed = Icon("git-pull-request-closed") +var GitPullRequestCreateArrow = Icon("git-pull-request-create-arrow") +var GitPullRequestCreate = Icon("git-pull-request-create") +var GitPullRequestDraft = Icon("git-pull-request-draft") +var GitPullRequest = Icon("git-pull-request") +var Github = Icon("github") +var Gitlab = Icon("gitlab") +var GlassWater = Icon("glass-water") +var Glasses = Icon("glasses") +var GlobeLock = Icon("globe-lock") +var Globe = Icon("globe") +var Goal = Icon("goal") +var Grab = Icon("grab") +var GraduationCap = Icon("graduation-cap") +var Grape = Icon("grape") +var Grid2x2Check = Icon("grid-2x2-check") +var Grid2x2Plus = Icon("grid-2x2-plus") +var Grid2x2X = Icon("grid-2x2-x") +var Grid2x2 = Icon("grid-2x2") +var Grid3x3 = Icon("grid-3x3") +var GripHorizontal = Icon("grip-horizontal") +var GripVertical = Icon("grip-vertical") +var Grip = Icon("grip") +var Group = Icon("group") +var Guitar = Icon("guitar") +var Ham = Icon("ham") +var Hammer = Icon("hammer") +var HandCoins = Icon("hand-coins") +var HandHeart = Icon("hand-heart") +var HandHelping = Icon("hand-helping") +var HandMetal = Icon("hand-metal") +var HandPlatter = Icon("hand-platter") +var Hand = Icon("hand") +var Handshake = Icon("handshake") +var HardDriveDownload = Icon("hard-drive-download") +var HardDriveUpload = Icon("hard-drive-upload") +var HardDrive = Icon("hard-drive") +var HardHat = Icon("hard-hat") +var Hash = Icon("hash") +var Haze = Icon("haze") +var HdmiPort = Icon("hdmi-port") +var Heading1 = Icon("heading-1") +var Heading2 = Icon("heading-2") +var Heading3 = Icon("heading-3") +var Heading4 = Icon("heading-4") +var Heading5 = Icon("heading-5") +var Heading6 = Icon("heading-6") +var Heading = Icon("heading") +var HeadphoneOff = Icon("headphone-off") +var Headphones = Icon("headphones") +var Headset = Icon("headset") +var HeartCrack = Icon("heart-crack") +var HeartHandshake = Icon("heart-handshake") +var HeartOff = Icon("heart-off") +var HeartPulse = Icon("heart-pulse") +var Heart = Icon("heart") +var Heater = Icon("heater") +var Hexagon = Icon("hexagon") +var Highlighter = Icon("highlighter") +var History = Icon("history") +var HopOff = Icon("hop-off") +var Hop = Icon("hop") +var Hospital = Icon("hospital") +var Hotel = Icon("hotel") +var Hourglass = Icon("hourglass") +var HousePlug = Icon("house-plug") +var HousePlus = Icon("house-plus") +var House = Icon("house") +var IceCreamBowl = Icon("ice-cream-bowl") +var IceCreamCone = Icon("ice-cream-cone") +var IdCard = Icon("id-card") +var ImageDown = Icon("image-down") +var ImageMinus = Icon("image-minus") +var ImageOff = Icon("image-off") +var ImagePlay = Icon("image-play") +var ImagePlus = Icon("image-plus") +var ImageUp = Icon("image-up") +var Image = Icon("image") +var Images = Icon("images") +var Import = Icon("import") +var Inbox = Icon("inbox") +var IndentDecrease = Icon("indent-decrease") +var IndentIncrease = Icon("indent-increase") +var IndianRupee = Icon("indian-rupee") +var Infinity = Icon("infinity") +var Info = Icon("info") +var InspectionPanel = Icon("inspection-panel") +var Instagram = Icon("instagram") +var Italic = Icon("italic") +var IterationCcw = Icon("iteration-ccw") +var IterationCw = Icon("iteration-cw") +var JapaneseYen = Icon("japanese-yen") +var Joystick = Icon("joystick") +var Kanban = Icon("kanban") +var KeyRound = Icon("key-round") +var KeySquare = Icon("key-square") +var Key = Icon("key") +var KeyboardMusic = Icon("keyboard-music") +var KeyboardOff = Icon("keyboard-off") +var Keyboard = Icon("keyboard") +var LampCeiling = Icon("lamp-ceiling") +var LampDesk = Icon("lamp-desk") +var LampFloor = Icon("lamp-floor") +var LampWallDown = Icon("lamp-wall-down") +var LampWallUp = Icon("lamp-wall-up") +var Lamp = Icon("lamp") +var LandPlot = Icon("land-plot") +var Landmark = Icon("landmark") +var Languages = Icon("languages") +var LaptopMinimal = Icon("laptop-minimal") +var Laptop = Icon("laptop") +var LassoSelect = Icon("lasso-select") +var Lasso = Icon("lasso") +var Laugh = Icon("laugh") +var Layers2 = Icon("layers-2") +var Layers3 = Icon("layers-3") +var Layers = Icon("layers") +var LayoutDashboard = Icon("layout-dashboard") +var LayoutGrid = Icon("layout-grid") +var LayoutList = Icon("layout-list") +var LayoutPanelLeft = Icon("layout-panel-left") +var LayoutPanelTop = Icon("layout-panel-top") +var LayoutTemplate = Icon("layout-template") +var Leaf = Icon("leaf") +var LeafyGreen = Icon("leafy-green") +var Lectern = Icon("lectern") +var LetterText = Icon("letter-text") +var LibraryBig = Icon("library-big") +var Library = Icon("library") +var LifeBuoy = Icon("life-buoy") +var Ligature = Icon("ligature") +var LightbulbOff = Icon("lightbulb-off") +var Lightbulb = Icon("lightbulb") +var Link2Off = Icon("link-2-off") +var Link2 = Icon("link-2") +var Link = Icon("link") +var Linkedin = Icon("linkedin") +var ListCheck = Icon("list-check") +var ListChecks = Icon("list-checks") +var ListCollapse = Icon("list-collapse") +var ListEnd = Icon("list-end") +var ListFilter = Icon("list-filter") +var ListMinus = Icon("list-minus") +var ListMusic = Icon("list-music") +var ListOrdered = Icon("list-ordered") +var ListPlus = Icon("list-plus") +var ListRestart = Icon("list-restart") +var ListStart = Icon("list-start") +var ListTodo = Icon("list-todo") +var ListTree = Icon("list-tree") +var ListVideo = Icon("list-video") +var ListX = Icon("list-x") +var List = Icon("list") +var LoaderCircle = Icon("loader-circle") +var LoaderPinwheel = Icon("loader-pinwheel") +var Loader = Icon("loader") +var LocateFixed = Icon("locate-fixed") +var LocateOff = Icon("locate-off") +var Locate = Icon("locate") +var LockKeyholeOpen = Icon("lock-keyhole-open") +var LockKeyhole = Icon("lock-keyhole") +var LockOpen = Icon("lock-open") +var Lock = Icon("lock") +var LogIn = Icon("log-in") +var LogOut = Icon("log-out") +var Logs = Icon("logs") +var Lollipop = Icon("lollipop") +var Luggage = Icon("luggage") +var Magnet = Icon("magnet") +var MailCheck = Icon("mail-check") +var MailMinus = Icon("mail-minus") +var MailOpen = Icon("mail-open") +var MailPlus = Icon("mail-plus") +var MailQuestion = Icon("mail-question") +var MailSearch = Icon("mail-search") +var MailWarning = Icon("mail-warning") +var MailX = Icon("mail-x") +var Mail = Icon("mail") +var Mailbox = Icon("mailbox") +var Mails = Icon("mails") +var MapPinCheckInside = Icon("map-pin-check-inside") +var MapPinCheck = Icon("map-pin-check") +var MapPinHouse = Icon("map-pin-house") +var MapPinMinusInside = Icon("map-pin-minus-inside") +var MapPinMinus = Icon("map-pin-minus") +var MapPinOff = Icon("map-pin-off") +var MapPinPlusInside = Icon("map-pin-plus-inside") +var MapPinPlus = Icon("map-pin-plus") +var MapPinXInside = Icon("map-pin-x-inside") +var MapPinX = Icon("map-pin-x") +var MapPin = Icon("map-pin") +var MapPinned = Icon("map-pinned") +var Map = Icon("map") +var Martini = Icon("martini") +var Maximize2 = Icon("maximize-2") +var Maximize = Icon("maximize") +var Medal = Icon("medal") +var MegaphoneOff = Icon("megaphone-off") +var Megaphone = Icon("megaphone") +var Meh = Icon("meh") +var MemoryStick = Icon("memory-stick") +var Menu = Icon("menu") +var Merge = Icon("merge") +var MessageCircleCode = Icon("message-circle-code") +var MessageCircleDashed = Icon("message-circle-dashed") +var MessageCircleHeart = Icon("message-circle-heart") +var MessageCircleMore = Icon("message-circle-more") +var MessageCircleOff = Icon("message-circle-off") +var MessageCirclePlus = Icon("message-circle-plus") +var MessageCircleQuestion = Icon("message-circle-question") +var MessageCircleReply = Icon("message-circle-reply") +var MessageCircleWarning = Icon("message-circle-warning") +var MessageCircleX = Icon("message-circle-x") +var MessageCircle = Icon("message-circle") +var MessageSquareCode = Icon("message-square-code") +var MessageSquareDashed = Icon("message-square-dashed") +var MessageSquareDiff = Icon("message-square-diff") +var MessageSquareDot = Icon("message-square-dot") +var MessageSquareHeart = Icon("message-square-heart") +var MessageSquareLock = Icon("message-square-lock") +var MessageSquareMore = Icon("message-square-more") +var MessageSquareOff = Icon("message-square-off") +var MessageSquarePlus = Icon("message-square-plus") +var MessageSquareQuote = Icon("message-square-quote") +var MessageSquareReply = Icon("message-square-reply") +var MessageSquareShare = Icon("message-square-share") +var MessageSquareText = Icon("message-square-text") +var MessageSquareWarning = Icon("message-square-warning") +var MessageSquareX = Icon("message-square-x") +var MessageSquare = Icon("message-square") +var MessagesSquare = Icon("messages-square") +var MicOff = Icon("mic-off") +var MicVocal = Icon("mic-vocal") +var Mic = Icon("mic") +var Microchip = Icon("microchip") +var Microscope = Icon("microscope") +var Microwave = Icon("microwave") +var Milestone = Icon("milestone") +var MilkOff = Icon("milk-off") +var Milk = Icon("milk") +var Minimize2 = Icon("minimize-2") +var Minimize = Icon("minimize") +var Minus = Icon("minus") +var MonitorCheck = Icon("monitor-check") +var MonitorCog = Icon("monitor-cog") +var MonitorDot = Icon("monitor-dot") +var MonitorDown = Icon("monitor-down") +var MonitorOff = Icon("monitor-off") +var MonitorPause = Icon("monitor-pause") +var MonitorPlay = Icon("monitor-play") +var MonitorSmartphone = Icon("monitor-smartphone") +var MonitorSpeaker = Icon("monitor-speaker") +var MonitorStop = Icon("monitor-stop") +var MonitorUp = Icon("monitor-up") +var MonitorX = Icon("monitor-x") +var Monitor = Icon("monitor") +var MoonStar = Icon("moon-star") +var Moon = Icon("moon") +var MountainSnow = Icon("mountain-snow") +var Mountain = Icon("mountain") +var MouseOff = Icon("mouse-off") +var MousePointer2 = Icon("mouse-pointer-2") +var MousePointerBan = Icon("mouse-pointer-ban") +var MousePointerClick = Icon("mouse-pointer-click") +var MousePointer = Icon("mouse-pointer") +var Mouse = Icon("mouse") +var Move3d = Icon("move-3d") +var MoveDiagonal2 = Icon("move-diagonal-2") +var MoveDiagonal = Icon("move-diagonal") +var MoveDownLeft = Icon("move-down-left") +var MoveDownRight = Icon("move-down-right") +var MoveDown = Icon("move-down") +var MoveHorizontal = Icon("move-horizontal") +var MoveLeft = Icon("move-left") +var MoveRight = Icon("move-right") +var MoveUpLeft = Icon("move-up-left") +var MoveUpRight = Icon("move-up-right") +var MoveUp = Icon("move-up") +var MoveVertical = Icon("move-vertical") +var Move = Icon("move") +var Music2 = Icon("music-2") +var Music3 = Icon("music-3") +var Music4 = Icon("music-4") +var Music = Icon("music") +var Navigation2Off = Icon("navigation-2-off") +var Navigation2 = Icon("navigation-2") +var NavigationOff = Icon("navigation-off") +var Navigation = Icon("navigation") +var Network = Icon("network") +var Newspaper = Icon("newspaper") +var Nfc = Icon("nfc") +var NotebookPen = Icon("notebook-pen") +var NotebookTabs = Icon("notebook-tabs") +var NotebookText = Icon("notebook-text") +var Notebook = Icon("notebook") +var NotepadTextDashed = Icon("notepad-text-dashed") +var NotepadText = Icon("notepad-text") +var NutOff = Icon("nut-off") +var Nut = Icon("nut") +var OctagonAlert = Icon("octagon-alert") +var OctagonMinus = Icon("octagon-minus") +var OctagonPause = Icon("octagon-pause") +var OctagonX = Icon("octagon-x") +var Octagon = Icon("octagon") +var Omega = Icon("omega") +var Option = Icon("option") +var Orbit = Icon("orbit") +var Origami = Icon("origami") +var Package2 = Icon("package-2") +var PackageCheck = Icon("package-check") +var PackageMinus = Icon("package-minus") +var PackageOpen = Icon("package-open") +var PackagePlus = Icon("package-plus") +var PackageSearch = Icon("package-search") +var PackageX = Icon("package-x") +var Package = Icon("package") +var PaintBucket = Icon("paint-bucket") +var PaintRoller = Icon("paint-roller") +var PaintbrushVertical = Icon("paintbrush-vertical") +var Paintbrush = Icon("paintbrush") +var Palette = Icon("palette") +var PanelBottomClose = Icon("panel-bottom-close") +var PanelBottomDashed = Icon("panel-bottom-dashed") +var PanelBottomOpen = Icon("panel-bottom-open") +var PanelBottom = Icon("panel-bottom") +var PanelLeftClose = Icon("panel-left-close") +var PanelLeftDashed = Icon("panel-left-dashed") +var PanelLeftOpen = Icon("panel-left-open") +var PanelLeft = Icon("panel-left") +var PanelRightClose = Icon("panel-right-close") +var PanelRightDashed = Icon("panel-right-dashed") +var PanelRightOpen = Icon("panel-right-open") +var PanelRight = Icon("panel-right") +var PanelTopClose = Icon("panel-top-close") +var PanelTopDashed = Icon("panel-top-dashed") +var PanelTopOpen = Icon("panel-top-open") +var PanelTop = Icon("panel-top") +var PanelsLeftBottom = Icon("panels-left-bottom") +var PanelsRightBottom = Icon("panels-right-bottom") +var PanelsTopLeft = Icon("panels-top-left") +var Paperclip = Icon("paperclip") +var Parentheses = Icon("parentheses") +var ParkingMeter = Icon("parking-meter") +var PartyPopper = Icon("party-popper") +var Pause = Icon("pause") +var PawPrint = Icon("paw-print") +var PcCase = Icon("pc-case") +var PenLine = Icon("pen-line") +var PenOff = Icon("pen-off") +var PenTool = Icon("pen-tool") +var Pen = Icon("pen") +var PencilLine = Icon("pencil-line") +var PencilOff = Icon("pencil-off") +var PencilRuler = Icon("pencil-ruler") +var Pencil = Icon("pencil") +var Pentagon = Icon("pentagon") +var Percent = Icon("percent") +var PersonStanding = Icon("person-standing") +var PhilippinePeso = Icon("philippine-peso") +var PhoneCall = Icon("phone-call") +var PhoneForwarded = Icon("phone-forwarded") +var PhoneIncoming = Icon("phone-incoming") +var PhoneMissed = Icon("phone-missed") +var PhoneOff = Icon("phone-off") +var PhoneOutgoing = Icon("phone-outgoing") +var Phone = Icon("phone") +var Pi = Icon("pi") +var Piano = Icon("piano") +var Pickaxe = Icon("pickaxe") +var PictureInPicture2 = Icon("picture-in-picture-2") +var PictureInPicture = Icon("picture-in-picture") +var PiggyBank = Icon("piggy-bank") +var PilcrowLeft = Icon("pilcrow-left") +var PilcrowRight = Icon("pilcrow-right") +var Pilcrow = Icon("pilcrow") +var PillBottle = Icon("pill-bottle") +var Pill = Icon("pill") +var PinOff = Icon("pin-off") +var Pin = Icon("pin") +var Pipette = Icon("pipette") +var Pizza = Icon("pizza") +var PlaneLanding = Icon("plane-landing") +var PlaneTakeoff = Icon("plane-takeoff") +var Plane = Icon("plane") +var Play = Icon("play") +var Plug2 = Icon("plug-2") +var PlugZap = Icon("plug-zap") +var Plug = Icon("plug") +var Plus = Icon("plus") +var PocketKnife = Icon("pocket-knife") +var Pocket = Icon("pocket") +var Podcast = Icon("podcast") +var PointerOff = Icon("pointer-off") +var Pointer = Icon("pointer") +var Popcorn = Icon("popcorn") +var Popsicle = Icon("popsicle") +var PoundSterling = Icon("pound-sterling") +var PowerOff = Icon("power-off") +var Power = Icon("power") +var Presentation = Icon("presentation") +var PrinterCheck = Icon("printer-check") +var Printer = Icon("printer") +var Projector = Icon("projector") +var Proportions = Icon("proportions") +var Puzzle = Icon("puzzle") +var Pyramid = Icon("pyramid") +var QrCode = Icon("qr-code") +var Quote = Icon("quote") +var Rabbit = Icon("rabbit") +var Radar = Icon("radar") +var Radiation = Icon("radiation") +var Radical = Icon("radical") +var RadioReceiver = Icon("radio-receiver") +var RadioTower = Icon("radio-tower") +var Radio = Icon("radio") +var Radius = Icon("radius") +var RailSymbol = Icon("rail-symbol") +var Rainbow = Icon("rainbow") +var Rat = Icon("rat") +var Ratio = Icon("ratio") +var ReceiptCent = Icon("receipt-cent") +var ReceiptEuro = Icon("receipt-euro") +var ReceiptIndianRupee = Icon("receipt-indian-rupee") +var ReceiptJapaneseYen = Icon("receipt-japanese-yen") +var ReceiptPoundSterling = Icon("receipt-pound-sterling") +var ReceiptRussianRuble = Icon("receipt-russian-ruble") +var ReceiptSwissFranc = Icon("receipt-swiss-franc") +var ReceiptText = Icon("receipt-text") +var Receipt = Icon("receipt") +var RectangleEllipsis = Icon("rectangle-ellipsis") +var RectangleHorizontal = Icon("rectangle-horizontal") +var RectangleVertical = Icon("rectangle-vertical") +var Recycle = Icon("recycle") +var Redo2 = Icon("redo-2") +var RedoDot = Icon("redo-dot") +var Redo = Icon("redo") +var RefreshCcwDot = Icon("refresh-ccw-dot") +var RefreshCcw = Icon("refresh-ccw") +var RefreshCwOff = Icon("refresh-cw-off") +var RefreshCw = Icon("refresh-cw") +var Refrigerator = Icon("refrigerator") +var Regex = Icon("regex") +var RemoveFormatting = Icon("remove-formatting") +var Repeat1 = Icon("repeat-1") +var Repeat2 = Icon("repeat-2") +var Repeat = Icon("repeat") +var ReplaceAll = Icon("replace-all") +var Replace = Icon("replace") +var ReplyAll = Icon("reply-all") +var Reply = Icon("reply") +var Rewind = Icon("rewind") +var Ribbon = Icon("ribbon") +var Rocket = Icon("rocket") +var RockingChair = Icon("rocking-chair") +var RollerCoaster = Icon("roller-coaster") +var Rotate3d = Icon("rotate-3d") +var RotateCcwSquare = Icon("rotate-ccw-square") +var RotateCcw = Icon("rotate-ccw") +var RotateCwSquare = Icon("rotate-cw-square") +var RotateCw = Icon("rotate-cw") +var RouteOff = Icon("route-off") +var Route = Icon("route") +var Router = Icon("router") +var Rows2 = Icon("rows-2") +var Rows3 = Icon("rows-3") +var Rows4 = Icon("rows-4") +var Rss = Icon("rss") +var Ruler = Icon("ruler") +var RussianRuble = Icon("russian-ruble") +var Sailboat = Icon("sailboat") +var Salad = Icon("salad") +var Sandwich = Icon("sandwich") +var SatelliteDish = Icon("satellite-dish") +var Satellite = Icon("satellite") +var SaveAll = Icon("save-all") +var SaveOff = Icon("save-off") +var Save = Icon("save") +var Scale3d = Icon("scale-3d") +var Scale = Icon("scale") +var Scaling = Icon("scaling") +var ScanBarcode = Icon("scan-barcode") +var ScanEye = Icon("scan-eye") +var ScanFace = Icon("scan-face") +var ScanLine = Icon("scan-line") +var ScanQrCode = Icon("scan-qr-code") +var ScanSearch = Icon("scan-search") +var ScanText = Icon("scan-text") +var Scan = Icon("scan") +var School = Icon("school") +var ScissorsLineDashed = Icon("scissors-line-dashed") +var Scissors = Icon("scissors") +var ScreenShareOff = Icon("screen-share-off") +var ScreenShare = Icon("screen-share") +var ScrollText = Icon("scroll-text") +var Scroll = Icon("scroll") +var SearchCheck = Icon("search-check") +var SearchCode = Icon("search-code") +var SearchSlash = Icon("search-slash") +var SearchX = Icon("search-x") +var Search = Icon("search") +var Section = Icon("section") +var SendHorizontal = Icon("send-horizontal") +var SendToBack = Icon("send-to-back") +var Send = Icon("send") +var SeparatorHorizontal = Icon("separator-horizontal") +var SeparatorVertical = Icon("separator-vertical") +var ServerCog = Icon("server-cog") +var ServerCrash = Icon("server-crash") +var ServerOff = Icon("server-off") +var Server = Icon("server") +var Settings2 = Icon("settings-2") +var Settings = Icon("settings") +var Shapes = Icon("shapes") +var Share2 = Icon("share-2") +var Share = Icon("share") +var Sheet = Icon("sheet") +var Shell = Icon("shell") +var ShieldAlert = Icon("shield-alert") +var ShieldBan = Icon("shield-ban") +var ShieldCheck = Icon("shield-check") +var ShieldEllipsis = Icon("shield-ellipsis") +var ShieldHalf = Icon("shield-half") +var ShieldMinus = Icon("shield-minus") +var ShieldOff = Icon("shield-off") +var ShieldPlus = Icon("shield-plus") +var ShieldQuestion = Icon("shield-question") +var ShieldX = Icon("shield-x") +var Shield = Icon("shield") +var ShipWheel = Icon("ship-wheel") +var Ship = Icon("ship") +var Shirt = Icon("shirt") +var ShoppingBag = Icon("shopping-bag") +var ShoppingBasket = Icon("shopping-basket") +var ShoppingCart = Icon("shopping-cart") +var Shovel = Icon("shovel") +var ShowerHead = Icon("shower-head") +var Shrink = Icon("shrink") +var Shrub = Icon("shrub") +var Shuffle = Icon("shuffle") +var Sigma = Icon("sigma") +var SignalHigh = Icon("signal-high") +var SignalLow = Icon("signal-low") +var SignalMedium = Icon("signal-medium") +var SignalZero = Icon("signal-zero") +var Signal = Icon("signal") +var Signature = Icon("signature") +var SignpostBig = Icon("signpost-big") +var Signpost = Icon("signpost") +var Siren = Icon("siren") +var SkipBack = Icon("skip-back") +var SkipForward = Icon("skip-forward") +var Skull = Icon("skull") +var Slack = Icon("slack") +var Slash = Icon("slash") +var Slice = Icon("slice") +var SlidersHorizontal = Icon("sliders-horizontal") +var SlidersVertical = Icon("sliders-vertical") +var SmartphoneCharging = Icon("smartphone-charging") +var SmartphoneNfc = Icon("smartphone-nfc") +var Smartphone = Icon("smartphone") +var SmilePlus = Icon("smile-plus") +var Smile = Icon("smile") +var Snail = Icon("snail") +var Snowflake = Icon("snowflake") +var Sofa = Icon("sofa") +var Soup = Icon("soup") +var Space = Icon("space") +var Spade = Icon("spade") +var Sparkle = Icon("sparkle") +var Sparkles = Icon("sparkles") +var Speaker = Icon("speaker") +var Speech = Icon("speech") +var SpellCheck2 = Icon("spell-check-2") +var SpellCheck = Icon("spell-check") +var Spline = Icon("spline") +var Split = Icon("split") +var SprayCan = Icon("spray-can") +var Sprout = Icon("sprout") +var SquareActivity = Icon("square-activity") +var SquareArrowDownLeft = Icon("square-arrow-down-left") +var SquareArrowDownRight = Icon("square-arrow-down-right") +var SquareArrowDown = Icon("square-arrow-down") +var SquareArrowLeft = Icon("square-arrow-left") +var SquareArrowOutDownLeft = Icon("square-arrow-out-down-left") +var SquareArrowOutDownRight = Icon("square-arrow-out-down-right") +var SquareArrowOutUpLeft = Icon("square-arrow-out-up-left") +var SquareArrowOutUpRight = Icon("square-arrow-out-up-right") +var SquareArrowRight = Icon("square-arrow-right") +var SquareArrowUpLeft = Icon("square-arrow-up-left") +var SquareArrowUpRight = Icon("square-arrow-up-right") +var SquareArrowUp = Icon("square-arrow-up") +var SquareAsterisk = Icon("square-asterisk") +var SquareBottomDashedScissors = Icon("square-bottom-dashed-scissors") +var SquareChartGantt = Icon("square-chart-gantt") +var SquareCheckBig = Icon("square-check-big") +var SquareCheck = Icon("square-check") +var SquareChevronDown = Icon("square-chevron-down") +var SquareChevronLeft = Icon("square-chevron-left") +var SquareChevronRight = Icon("square-chevron-right") +var SquareChevronUp = Icon("square-chevron-up") +var SquareCode = Icon("square-code") +var SquareDashedBottomCode = Icon("square-dashed-bottom-code") +var SquareDashedBottom = Icon("square-dashed-bottom") +var SquareDashedKanban = Icon("square-dashed-kanban") +var SquareDashedMousePointer = Icon("square-dashed-mouse-pointer") +var SquareDashed = Icon("square-dashed") +var SquareDivide = Icon("square-divide") +var SquareDot = Icon("square-dot") +var SquareEqual = Icon("square-equal") +var SquareFunction = Icon("square-function") +var SquareKanban = Icon("square-kanban") +var SquareLibrary = Icon("square-library") +var SquareM = Icon("square-m") +var SquareMenu = Icon("square-menu") +var SquareMinus = Icon("square-minus") +var SquareMousePointer = Icon("square-mouse-pointer") +var SquareParkingOff = Icon("square-parking-off") +var SquareParking = Icon("square-parking") +var SquarePen = Icon("square-pen") +var SquarePercent = Icon("square-percent") +var SquarePi = Icon("square-pi") +var SquarePilcrow = Icon("square-pilcrow") +var SquarePlay = Icon("square-play") +var SquarePlus = Icon("square-plus") +var SquarePower = Icon("square-power") +var SquareRadical = Icon("square-radical") +var SquareScissors = Icon("square-scissors") +var SquareSigma = Icon("square-sigma") +var SquareSlash = Icon("square-slash") +var SquareSplitHorizontal = Icon("square-split-horizontal") +var SquareSplitVertical = Icon("square-split-vertical") +var SquareSquare = Icon("square-square") +var SquareStack = Icon("square-stack") +var SquareTerminal = Icon("square-terminal") +var SquareUserRound = Icon("square-user-round") +var SquareUser = Icon("square-user") +var SquareX = Icon("square-x") +var Square = Icon("square") +var Squircle = Icon("squircle") +var Squirrel = Icon("squirrel") +var Stamp = Icon("stamp") +var StarHalf = Icon("star-half") +var StarOff = Icon("star-off") +var Star = Icon("star") +var StepBack = Icon("step-back") +var StepForward = Icon("step-forward") +var Stethoscope = Icon("stethoscope") +var Sticker = Icon("sticker") +var StickyNote = Icon("sticky-note") +var Store = Icon("store") +var StretchHorizontal = Icon("stretch-horizontal") +var StretchVertical = Icon("stretch-vertical") +var Strikethrough = Icon("strikethrough") +var Subscript = Icon("subscript") +var SunDim = Icon("sun-dim") +var SunMedium = Icon("sun-medium") +var SunMoon = Icon("sun-moon") +var SunSnow = Icon("sun-snow") +var Sun = Icon("sun") +var Sunrise = Icon("sunrise") +var Sunset = Icon("sunset") +var Superscript = Icon("superscript") +var SwatchBook = Icon("swatch-book") +var SwissFranc = Icon("swiss-franc") +var SwitchCamera = Icon("switch-camera") +var Sword = Icon("sword") +var Swords = Icon("swords") +var Syringe = Icon("syringe") +var Table2 = Icon("table-2") +var TableCellsMerge = Icon("table-cells-merge") +var TableCellsSplit = Icon("table-cells-split") +var TableColumnsSplit = Icon("table-columns-split") +var TableOfContents = Icon("table-of-contents") +var TableProperties = Icon("table-properties") +var TableRowsSplit = Icon("table-rows-split") +var Table = Icon("table") +var TabletSmartphone = Icon("tablet-smartphone") +var Tablet = Icon("tablet") +var Tablets = Icon("tablets") +var Tag = Icon("tag") +var Tags = Icon("tags") +var Tally1 = Icon("tally-1") +var Tally2 = Icon("tally-2") +var Tally3 = Icon("tally-3") +var Tally4 = Icon("tally-4") +var Tally5 = Icon("tally-5") +var Tangent = Icon("tangent") +var Target = Icon("target") +var Telescope = Icon("telescope") +var TentTree = Icon("tent-tree") +var Tent = Icon("tent") +var Terminal = Icon("terminal") +var TestTubeDiagonal = Icon("test-tube-diagonal") +var TestTube = Icon("test-tube") +var TestTubes = Icon("test-tubes") +var TextCursorInput = Icon("text-cursor-input") +var TextCursor = Icon("text-cursor") +var TextQuote = Icon("text-quote") +var TextSearch = Icon("text-search") +var TextSelect = Icon("text-select") +var Text = Icon("text") +var Theater = Icon("theater") +var ThermometerSnowflake = Icon("thermometer-snowflake") +var ThermometerSun = Icon("thermometer-sun") +var Thermometer = Icon("thermometer") +var ThumbsDown = Icon("thumbs-down") +var ThumbsUp = Icon("thumbs-up") +var TicketCheck = Icon("ticket-check") +var TicketMinus = Icon("ticket-minus") +var TicketPercent = Icon("ticket-percent") +var TicketPlus = Icon("ticket-plus") +var TicketSlash = Icon("ticket-slash") +var TicketX = Icon("ticket-x") +var Ticket = Icon("ticket") +var TicketsPlane = Icon("tickets-plane") +var Tickets = Icon("tickets") +var TimerOff = Icon("timer-off") +var TimerReset = Icon("timer-reset") +var Timer = Icon("timer") +var ToggleLeft = Icon("toggle-left") +var ToggleRight = Icon("toggle-right") +var Tornado = Icon("tornado") +var Torus = Icon("torus") +var TouchpadOff = Icon("touchpad-off") +var Touchpad = Icon("touchpad") +var TowerControl = Icon("tower-control") +var ToyBrick = Icon("toy-brick") +var Tractor = Icon("tractor") +var TrafficCone = Icon("traffic-cone") +var TrainFrontTunnel = Icon("train-front-tunnel") +var TrainFront = Icon("train-front") +var TrainTrack = Icon("train-track") +var TramFront = Icon("tram-front") +var Trash2 = Icon("trash-2") +var Trash = Icon("trash") +var TreeDeciduous = Icon("tree-deciduous") +var TreePalm = Icon("tree-palm") +var TreePine = Icon("tree-pine") +var Trees = Icon("trees") +var Trello = Icon("trello") +var TrendingDown = Icon("trending-down") +var TrendingUpDown = Icon("trending-up-down") +var TrendingUp = Icon("trending-up") +var TriangleAlert = Icon("triangle-alert") +var TriangleRight = Icon("triangle-right") +var Triangle = Icon("triangle") +var Trophy = Icon("trophy") +var Truck = Icon("truck") +var Turtle = Icon("turtle") +var TvMinimalPlay = Icon("tv-minimal-play") +var TvMinimal = Icon("tv-minimal") +var Tv = Icon("tv") +var Twitch = Icon("twitch") +var Twitter = Icon("twitter") +var TypeOutline = Icon("type-outline") +var Type = Icon("type") +var UmbrellaOff = Icon("umbrella-off") +var Umbrella = Icon("umbrella") +var Underline = Icon("underline") +var Undo2 = Icon("undo-2") +var UndoDot = Icon("undo-dot") +var Undo = Icon("undo") +var UnfoldHorizontal = Icon("unfold-horizontal") +var UnfoldVertical = Icon("unfold-vertical") +var Ungroup = Icon("ungroup") +var University = Icon("university") +var Unlink2 = Icon("unlink-2") +var Unlink = Icon("unlink") +var Unplug = Icon("unplug") +var Upload = Icon("upload") +var Usb = Icon("usb") +var UserCheck = Icon("user-check") +var UserCog = Icon("user-cog") +var UserMinus = Icon("user-minus") +var UserPen = Icon("user-pen") +var UserPlus = Icon("user-plus") +var UserRoundCheck = Icon("user-round-check") +var UserRoundCog = Icon("user-round-cog") +var UserRoundMinus = Icon("user-round-minus") +var UserRoundPen = Icon("user-round-pen") +var UserRoundPlus = Icon("user-round-plus") +var UserRoundSearch = Icon("user-round-search") +var UserRoundX = Icon("user-round-x") +var UserRound = Icon("user-round") +var UserSearch = Icon("user-search") +var UserX = Icon("user-x") +var User = Icon("user") +var UsersRound = Icon("users-round") +var Users = Icon("users") +var UtensilsCrossed = Icon("utensils-crossed") +var Utensils = Icon("utensils") +var UtilityPole = Icon("utility-pole") +var Variable = Icon("variable") +var Vault = Icon("vault") +var Vegan = Icon("vegan") +var VenetianMask = Icon("venetian-mask") +var VibrateOff = Icon("vibrate-off") +var Vibrate = Icon("vibrate") +var VideoOff = Icon("video-off") +var Video = Icon("video") +var Videotape = Icon("videotape") +var View = Icon("view") +var Voicemail = Icon("voicemail") +var Volleyball = Icon("volleyball") +var Volume1 = Icon("volume-1") +var Volume2 = Icon("volume-2") +var VolumeOff = Icon("volume-off") +var VolumeX = Icon("volume-x") +var Volume = Icon("volume") +var Vote = Icon("vote") +var WalletCards = Icon("wallet-cards") +var WalletMinimal = Icon("wallet-minimal") +var Wallet = Icon("wallet") +var Wallpaper = Icon("wallpaper") +var WandSparkles = Icon("wand-sparkles") +var Wand = Icon("wand") +var Warehouse = Icon("warehouse") +var WashingMachine = Icon("washing-machine") +var Watch = Icon("watch") +var Waves = Icon("waves") +var Waypoints = Icon("waypoints") +var Webcam = Icon("webcam") +var WebhookOff = Icon("webhook-off") +var Webhook = Icon("webhook") +var Weight = Icon("weight") +var WheatOff = Icon("wheat-off") +var Wheat = Icon("wheat") +var WholeWord = Icon("whole-word") +var WifiHigh = Icon("wifi-high") +var WifiLow = Icon("wifi-low") +var WifiOff = Icon("wifi-off") +var WifiZero = Icon("wifi-zero") +var Wifi = Icon("wifi") +var Wind = Icon("wind") +var WineOff = Icon("wine-off") +var Wine = Icon("wine") +var Workflow = Icon("workflow") +var Worm = Icon("worm") +var WrapText = Icon("wrap-text") +var Wrench = Icon("wrench") +var X = Icon("x") +var Youtube = Icon("youtube") +var ZapOff = Icon("zap-off") +var Zap = Icon("zap") +var ZoomIn = Icon("zoom-in") +var ZoomOut = Icon("zoom-out") + +================ +File: pkg/icons/icons.go +================ +// Package icons provides a set of Lucide icons for use with the templ library. +package icons + +import ( + "context" + "embed" + "fmt" + "io" + "strings" + "sync" + + "github.com/a-h/templ" +) + +// LucideVersion represents the version of Lucide icons used in this package. +const LucideVersion = "0.451.0" + +var ( + iconContents = make(map[string]string) + iconMutex sync.RWMutex +) + +//go:embed content/*.svg +var iconFS embed.FS + +// IconProps defines the properties that can be set for an icon. +type IconProps struct { + Size string + Color string + Fill string + Stroke string + Class string +} + +// Icon returns a function that generates a templ.Component for the specified icon. +func Icon(name string) func(IconProps) templ.Component { + return func(props IconProps) templ.Component { + return templ.ComponentFunc(func(ctx context.Context, w io.Writer) (err error) { + svg, err := generateSVG(name, props) + if err != nil { + return err + } + _, err = w.Write([]byte(svg)) + return + }) + } +} + +// generateSVG creates an SVG string for the specified icon with the given properties. +func generateSVG(name string, props IconProps) (string, error) { + content, err := getIconContent(name) + if err != nil { + return "", err + } + + size := props.Size + if size == "" { + size = "24" + } + + fill := props.Fill + if fill == "" { + fill = "none" + } + + stroke := props.Stroke + if stroke == "" { + stroke = props.Color + } + if stroke == "" { + stroke = "currentColor" + } + + return fmt.Sprintf(`%s`, + size, size, fill, stroke, props.Class, content), nil +} + +// getIconContent retrieves the content of an icon, loading it if necessary. +func getIconContent(name string) (string, error) { + iconMutex.RLock() + content, exists := iconContents[name] + iconMutex.RUnlock() + + if exists { + return content, nil + } + + iconMutex.Lock() + defer iconMutex.Unlock() + + // Check again in case another goroutine has loaded the icon + content, exists = iconContents[name] + if exists { + return content, nil + } + + // Load the icon content + content, err := loadIconContent(name) + if err != nil { + return "", err + } + + iconContents[name] = content + return content, nil +} + +// loadIconContent reads the content of an icon from the embedded filesystem. +func loadIconContent(name string) (string, error) { + content, err := iconFS.ReadFile(fmt.Sprintf("content/%s.svg", name)) + if err != nil { + return "", fmt.Errorf("icon %s not found: %w", name, err) + } + return extractSVGContent(string(content)), nil +} + +// extractSVGContent removes the outer SVG tags from the icon content. +func extractSVGContent(svgContent string) string { + start := strings.Index(svgContent, ">") + 1 + end := strings.LastIndex(svgContent, "") + if start == -1 || end == -1 { + return "" + } + return strings.TrimSpace(svgContent[start:end]) +} + +================ +File: pkg/styles/goilerplate.css +================ +/* +! tailwindcss v3.4.10 | MIT License | https://tailwindcss.com +*/ + +/* +1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4) +2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116) +*/ + +*, +::before, +::after { + box-sizing: border-box; + /* 1 */ + border-width: 0; + /* 2 */ + border-style: solid; + /* 2 */ + border-color: #e5e7eb; + /* 2 */ +} + +::before, +::after { + --tw-content: ''; +} + +/* +1. Use a consistent sensible line-height in all browsers. +2. Prevent adjustments of font size after orientation changes in iOS. +3. Use a more readable tab size. +4. Use the user's configured `sans` font-family by default. +5. Use the user's configured `sans` font-feature-settings by default. +6. Use the user's configured `sans` font-variation-settings by default. +7. Disable tap highlights on iOS +*/ + +html, +:host { + line-height: 1.5; + /* 1 */ + -webkit-text-size-adjust: 100%; + /* 2 */ + -moz-tab-size: 4; + /* 3 */ + -o-tab-size: 4; + tab-size: 4; + /* 3 */ + font-family: Inter, ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; + /* 4 */ + font-feature-settings: normal; + /* 5 */ + font-variation-settings: normal; + /* 6 */ + -webkit-tap-highlight-color: transparent; + /* 7 */ +} + +/* +1. Remove the margin in all browsers. +2. Inherit line-height from `html` so users can set them as a class directly on the `html` element. +*/ + +body { + margin: 0; + /* 1 */ + line-height: inherit; + /* 2 */ +} + +/* +1. Add the correct height in Firefox. +2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655) +3. Ensure horizontal rules are visible by default. +*/ + +hr { + height: 0; + /* 1 */ + color: inherit; + /* 2 */ + border-top-width: 1px; + /* 3 */ +} + +/* +Add the correct text decoration in Chrome, Edge, and Safari. +*/ + +abbr:where([title]) { + -webkit-text-decoration: underline dotted; + text-decoration: underline dotted; +} + +/* +Remove the default font size and weight for headings. +*/ + +h1, +h2, +h3, +h4, +h5, +h6 { + font-size: inherit; + font-weight: inherit; +} + +/* +Reset links to optimize for opt-in styling instead of opt-out. +*/ + +a { + color: inherit; + text-decoration: inherit; +} + +/* +Add the correct font weight in Edge and Safari. +*/ + +b, +strong { + font-weight: bolder; +} + +/* +1. Use the user's configured `mono` font-family by default. +2. Use the user's configured `mono` font-feature-settings by default. +3. Use the user's configured `mono` font-variation-settings by default. +4. Correct the odd `em` font sizing in all browsers. +*/ + +code, +kbd, +samp, +pre { + font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; + /* 1 */ + font-feature-settings: normal; + /* 2 */ + font-variation-settings: normal; + /* 3 */ + font-size: 1em; + /* 4 */ +} + +/* +Add the correct font size in all browsers. +*/ + +small { + font-size: 80%; +} + +/* +Prevent `sub` and `sup` elements from affecting the line height in all browsers. +*/ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sub { + bottom: -0.25em; +} + +sup { + top: -0.5em; +} + +/* +1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297) +2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016) +3. Remove gaps between table borders by default. +*/ + +table { + text-indent: 0; + /* 1 */ + border-color: inherit; + /* 2 */ + border-collapse: collapse; + /* 3 */ +} + +/* +1. Change the font styles in all browsers. +2. Remove the margin in Firefox and Safari. +3. Remove default padding in all browsers. +*/ + +button, +input, +optgroup, +select, +textarea { + font-family: inherit; + /* 1 */ + font-feature-settings: inherit; + /* 1 */ + font-variation-settings: inherit; + /* 1 */ + font-size: 100%; + /* 1 */ + font-weight: inherit; + /* 1 */ + line-height: inherit; + /* 1 */ + letter-spacing: inherit; + /* 1 */ + color: inherit; + /* 1 */ + margin: 0; + /* 2 */ + padding: 0; + /* 3 */ +} + +/* +Remove the inheritance of text transform in Edge and Firefox. +*/ + +button, +select { + text-transform: none; +} + +/* +1. Correct the inability to style clickable types in iOS and Safari. +2. Remove default button styles. +*/ + +button, +input:where([type='button']), +input:where([type='reset']), +input:where([type='submit']) { + -webkit-appearance: button; + /* 1 */ + background-color: transparent; + /* 2 */ + background-image: none; + /* 2 */ +} + +/* +Use the modern Firefox focus style for all focusable elements. +*/ + +:-moz-focusring { + outline: auto; +} + +/* +Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737) +*/ + +:-moz-ui-invalid { + box-shadow: none; +} + +/* +Add the correct vertical alignment in Chrome and Firefox. +*/ + +progress { + vertical-align: baseline; +} + +/* +Correct the cursor style of increment and decrement buttons in Safari. +*/ + +::-webkit-inner-spin-button, +::-webkit-outer-spin-button { + height: auto; +} + +/* +1. Correct the odd appearance in Chrome and Safari. +2. Correct the outline style in Safari. +*/ + +[type='search'] { + -webkit-appearance: textfield; + /* 1 */ + outline-offset: -2px; + /* 2 */ +} + +/* +Remove the inner padding in Chrome and Safari on macOS. +*/ + +::-webkit-search-decoration { + -webkit-appearance: none; +} + +/* +1. Correct the inability to style clickable types in iOS and Safari. +2. Change font properties to `inherit` in Safari. +*/ + +::-webkit-file-upload-button { + -webkit-appearance: button; + /* 1 */ + font: inherit; + /* 2 */ +} + +/* +Add the correct display in Chrome and Safari. +*/ + +summary { + display: list-item; +} + +/* +Removes the default spacing and border for appropriate elements. +*/ + +blockquote, +dl, +dd, +h1, +h2, +h3, +h4, +h5, +h6, +hr, +figure, +p, +pre { + margin: 0; +} + +fieldset { + margin: 0; + padding: 0; +} + +legend { + padding: 0; +} + +ol, +ul, +menu { + list-style: none; + margin: 0; + padding: 0; +} + +/* +Reset default styling for dialogs. +*/ + +dialog { + padding: 0; +} + +/* +Prevent resizing textareas horizontally by default. +*/ + +textarea { + resize: vertical; +} + +/* +1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300) +2. Set the default placeholder color to the user's configured gray 400 color. +*/ + +input::-moz-placeholder, textarea::-moz-placeholder { + opacity: 1; + /* 1 */ + color: #9ca3af; + /* 2 */ +} + +input::placeholder, +textarea::placeholder { + opacity: 1; + /* 1 */ + color: #9ca3af; + /* 2 */ +} + +/* +Set the default cursor for buttons. +*/ + +button, +[role="button"] { + cursor: pointer; +} + +/* +Make sure disabled buttons don't get the pointer cursor. +*/ + +:disabled { + cursor: default; +} + +/* +1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14) +2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210) + This can trigger a poorly considered lint error in some tools but is included by design. +*/ + +img, +svg, +video, +canvas, +audio, +iframe, +embed, +object { + display: block; + /* 1 */ + vertical-align: middle; + /* 2 */ +} + +/* +Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14) +*/ + +img, +video { + max-width: 100%; + height: auto; +} + +/* Make elements with the HTML hidden attribute stay hidden by default */ + +[hidden] { + display: none; +} + +:root { + --background: 0 0% 100%; + --foreground: 240 10% 3.9%; + --muted: 240 4.8% 95.9%; + --muted-foreground: 240 3.8% 46.1%; + --popover: 0 0% 100%; + --popover-foreground: 240 10% 3.9%; + --card: 0 0% 100%; + --card-foreground: 240 10% 3.9%; + --border: 240 5.9% 90%; + --input: 240 5.9% 90%; + --primary: 346.8 77.2% 49.8%; + --primary-foreground: 355.7 100% 97.3%; + --secondary: 240 4.8% 95.9%; + --secondary-foreground: 240 5.9% 10%; + --accent: 240 4.8% 95.9%; + --accent-foreground: 240 5.9% 10%; + --destructive: 0 84.2% 60.2%; + --destructive-foreground: 0 0% 98%; + --ring: 346.8 77.2% 49.8%; + --radius: 0.5rem; +} + +.dark { + --background: 20 14.3% 4.1%; + --foreground: 0 0% 95%; + --muted: 0 0% 15%; + --muted-foreground: 240 5% 64.9%; + --popover: 0 0% 9%; + --popover-foreground: 0 0% 95%; + --card: 24 9.8% 10%; + --card-foreground: 0 0% 95%; + --border: 240 3.7% 15.9%; + --input: 240 3.7% 15.9%; + --primary: 346.8 77.2% 49.8%; + --primary-foreground: 355.7 100% 97.3%; + --secondary: 240 3.7% 15.9%; + --secondary-foreground: 0 0% 98%; + --accent: 12 6.5% 15.1%; + --accent-foreground: 0 0% 98%; + --destructive: 0 62.8% 30.6%; + --destructive-foreground: 0 85.7% 97.3%; + --ring: 346.8 77.2% 49.8%; + --radius: 0.5rem; +} + +* { + --tw-border-opacity: 1; + border-color: hsl(var(--border) / var(--tw-border-opacity)); +} + +body { + --tw-bg-opacity: 1; + background-color: hsl(var(--background) / var(--tw-bg-opacity)); + --tw-text-opacity: 1; + color: hsl(var(--foreground) / var(--tw-text-opacity)); + font-feature-settings: + "rlig" 1, + "calt" 1; +} + +*, ::before, ::after { + --tw-border-spacing-x: 0; + --tw-border-spacing-y: 0; + --tw-translate-x: 0; + --tw-translate-y: 0; + --tw-rotate: 0; + --tw-skew-x: 0; + --tw-skew-y: 0; + --tw-scale-x: 1; + --tw-scale-y: 1; + --tw-pan-x: ; + --tw-pan-y: ; + --tw-pinch-zoom: ; + --tw-scroll-snap-strictness: proximity; + --tw-gradient-from-position: ; + --tw-gradient-via-position: ; + --tw-gradient-to-position: ; + --tw-ordinal: ; + --tw-slashed-zero: ; + --tw-numeric-figure: ; + --tw-numeric-spacing: ; + --tw-numeric-fraction: ; + --tw-ring-inset: ; + --tw-ring-offset-width: 0px; + --tw-ring-offset-color: #fff; + --tw-ring-color: rgb(59 130 246 / 0.5); + --tw-ring-offset-shadow: 0 0 #0000; + --tw-ring-shadow: 0 0 #0000; + --tw-shadow: 0 0 #0000; + --tw-shadow-colored: 0 0 #0000; + --tw-blur: ; + --tw-brightness: ; + --tw-contrast: ; + --tw-grayscale: ; + --tw-hue-rotate: ; + --tw-invert: ; + --tw-saturate: ; + --tw-sepia: ; + --tw-drop-shadow: ; + --tw-backdrop-blur: ; + --tw-backdrop-brightness: ; + --tw-backdrop-contrast: ; + --tw-backdrop-grayscale: ; + --tw-backdrop-hue-rotate: ; + --tw-backdrop-invert: ; + --tw-backdrop-opacity: ; + --tw-backdrop-saturate: ; + --tw-backdrop-sepia: ; + --tw-contain-size: ; + --tw-contain-layout: ; + --tw-contain-paint: ; + --tw-contain-style: ; +} + +::backdrop { + --tw-border-spacing-x: 0; + --tw-border-spacing-y: 0; + --tw-translate-x: 0; + --tw-translate-y: 0; + --tw-rotate: 0; + --tw-skew-x: 0; + --tw-skew-y: 0; + --tw-scale-x: 1; + --tw-scale-y: 1; + --tw-pan-x: ; + --tw-pan-y: ; + --tw-pinch-zoom: ; + --tw-scroll-snap-strictness: proximity; + --tw-gradient-from-position: ; + --tw-gradient-via-position: ; + --tw-gradient-to-position: ; + --tw-ordinal: ; + --tw-slashed-zero: ; + --tw-numeric-figure: ; + --tw-numeric-spacing: ; + --tw-numeric-fraction: ; + --tw-ring-inset: ; + --tw-ring-offset-width: 0px; + --tw-ring-offset-color: #fff; + --tw-ring-color: rgb(59 130 246 / 0.5); + --tw-ring-offset-shadow: 0 0 #0000; + --tw-ring-shadow: 0 0 #0000; + --tw-shadow: 0 0 #0000; + --tw-shadow-colored: 0 0 #0000; + --tw-blur: ; + --tw-brightness: ; + --tw-contrast: ; + --tw-grayscale: ; + --tw-hue-rotate: ; + --tw-invert: ; + --tw-saturate: ; + --tw-sepia: ; + --tw-drop-shadow: ; + --tw-backdrop-blur: ; + --tw-backdrop-brightness: ; + --tw-backdrop-contrast: ; + --tw-backdrop-grayscale: ; + --tw-backdrop-hue-rotate: ; + --tw-backdrop-invert: ; + --tw-backdrop-opacity: ; + --tw-backdrop-saturate: ; + --tw-backdrop-sepia: ; + --tw-contain-size: ; + --tw-contain-layout: ; + --tw-contain-paint: ; + --tw-contain-style: ; +} + +.container { + width: 100%; + margin-right: auto; + margin-left: auto; + padding-right: 2rem; + padding-left: 2rem; +} + +@media (min-width: 1400px) { + .container { + max-width: 1400px; + } +} + +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border-width: 0; +} + +.pointer-events-none { + pointer-events: none; +} + +.invisible { + visibility: hidden; +} + +.static { + position: static; +} + +.fixed { + position: fixed; +} + +.absolute { + position: absolute; +} + +.relative { + position: relative; +} + +.inset-0 { + inset: 0px; +} + +.inset-x-0 { + left: 0px; + right: 0px; +} + +.inset-y-0 { + top: 0px; + bottom: 0px; +} + +.bottom-0 { + bottom: 0px; +} + +.bottom-4 { + bottom: 1rem; +} + +.bottom-full { + bottom: 100%; +} + +.left-0 { + left: 0px; +} + +.left-1\/2 { + left: 50%; +} + +.left-full { + left: 100%; +} + +.right-0 { + right: 0px; +} + +.right-3 { + right: 0.75rem; +} + +.right-4 { + right: 1rem; +} + +.top-0 { + top: 0px; +} + +.top-1\/2 { + top: 50%; +} + +.top-3 { + top: 0.75rem; +} + +.top-full { + top: 100%; +} + +.z-10 { + z-index: 10; +} + +.z-20 { + z-index: 20; +} + +.z-50 { + z-index: 50; +} + +.m-0 { + margin: 0px; +} + +.mx-auto { + margin-left: auto; + margin-right: auto; +} + +.mb-1 { + margin-bottom: 0.25rem; +} + +.mb-2 { + margin-bottom: 0.5rem; +} + +.mb-3 { + margin-bottom: 0.75rem; +} + +.mb-4 { + margin-bottom: 1rem; +} + +.ml-1 { + margin-left: 0.25rem; +} + +.ml-auto { + margin-left: auto; +} + +.mr-2 { + margin-right: 0.5rem; +} + +.mt-1 { + margin-top: 0.25rem; +} + +.mt-2 { + margin-top: 0.5rem; +} + +.mt-4 { + margin-top: 1rem; +} + +.block { + display: block; +} + +.inline-block { + display: inline-block; +} + +.flex { + display: flex; +} + +.inline-flex { + display: inline-flex; +} + +.table { + display: table; +} + +.grid { + display: grid; +} + +.hidden { + display: none; +} + +.aspect-square { + aspect-ratio: 1 / 1; +} + +.size-3 { + width: 0.75rem; + height: 0.75rem; +} + +.size-4 { + width: 1rem; + height: 1rem; +} + +.h-1\/2 { + height: 50%; +} + +.h-10 { + height: 2.5rem; +} + +.h-11 { + height: 2.75rem; +} + +.h-12 { + height: 3rem; +} + +.h-16 { + height: 4rem; +} + +.h-4 { + height: 1rem; +} + +.h-5 { + height: 1.25rem; +} + +.h-6 { + height: 1.5rem; +} + +.h-7 { + height: 1.75rem; +} + +.h-8 { + height: 2rem; +} + +.h-9 { + height: 2.25rem; +} + +.h-auto { + height: auto; +} + +.h-full { + height: 100%; +} + +.max-h-\[50vh\] { + max-height: 50vh; +} + +.w-1\/3 { + width: 33.333333%; +} + +.w-10 { + width: 2.5rem; +} + +.w-12 { + width: 3rem; +} + +.w-16 { + width: 4rem; +} + +.w-3\/4 { + width: 75%; +} + +.w-4 { + width: 1rem; +} + +.w-56 { + width: 14rem; +} + +.w-64 { + width: 16rem; +} + +.w-7 { + width: 1.75rem; +} + +.w-8 { + width: 2rem; +} + +.w-full { + width: 100%; +} + +.max-w-md { + max-width: 28rem; +} + +.max-w-sm { + max-width: 24rem; +} + +.flex-1 { + flex: 1 1 0%; +} + +.shrink { + flex-shrink: 1; +} + +.-translate-x-1\/2 { + --tw-translate-x: -50%; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.-translate-x-full { + --tw-translate-x: -100%; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.-translate-y-1\/2 { + --tw-translate-y: -50%; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.-translate-y-full { + --tw-translate-y: -100%; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.translate-x-0 { + --tw-translate-x: 0px; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.translate-x-full { + --tw-translate-x: 100%; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.translate-y-0 { + --tw-translate-y: 0px; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.translate-y-full { + --tw-translate-y: 100%; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.scale-100 { + --tw-scale-x: 1; + --tw-scale-y: 1; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.scale-95 { + --tw-scale-x: .95; + --tw-scale-y: .95; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.transform { + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.cursor-not-allowed { + cursor: not-allowed; +} + +.cursor-pointer { + cursor: pointer; +} + +.select-none { + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; +} + +.appearance-none { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; +} + +.columns-2 { + -moz-columns: 2; + columns: 2; +} + +.columns-3 { + -moz-columns: 3; + columns: 3; +} + +.columns-4 { + -moz-columns: 4; + columns: 4; +} + +.grid-cols-7 { + grid-template-columns: repeat(7, minmax(0, 1fr)); +} + +.flex-col { + flex-direction: column; +} + +.items-start { + align-items: flex-start; +} + +.items-center { + align-items: center; +} + +.justify-start { + justify-content: flex-start; +} + +.justify-center { + justify-content: center; +} + +.justify-between { + justify-content: space-between; +} + +.gap-2 { + gap: 0.5rem; +} + +.gap-4 { + gap: 1rem; +} + +.space-x-2 > :not([hidden]) ~ :not([hidden]) { + --tw-space-x-reverse: 0; + margin-right: calc(0.5rem * var(--tw-space-x-reverse)); + margin-left: calc(0.5rem * calc(1 - var(--tw-space-x-reverse))); +} + +.space-y-1 > :not([hidden]) ~ :not([hidden]) { + --tw-space-y-reverse: 0; + margin-top: calc(0.25rem * calc(1 - var(--tw-space-y-reverse))); + margin-bottom: calc(0.25rem * var(--tw-space-y-reverse)); +} + +.space-y-1\.5 > :not([hidden]) ~ :not([hidden]) { + --tw-space-y-reverse: 0; + margin-top: calc(0.375rem * calc(1 - var(--tw-space-y-reverse))); + margin-bottom: calc(0.375rem * var(--tw-space-y-reverse)); +} + +.space-y-2 > :not([hidden]) ~ :not([hidden]) { + --tw-space-y-reverse: 0; + margin-top: calc(0.5rem * calc(1 - var(--tw-space-y-reverse))); + margin-bottom: calc(0.5rem * var(--tw-space-y-reverse)); +} + +.space-y-4 > :not([hidden]) ~ :not([hidden]) { + --tw-space-y-reverse: 0; + margin-top: calc(1rem * calc(1 - var(--tw-space-y-reverse))); + margin-bottom: calc(1rem * var(--tw-space-y-reverse)); +} + +.space-y-6 > :not([hidden]) ~ :not([hidden]) { + --tw-space-y-reverse: 0; + margin-top: calc(1.5rem * calc(1 - var(--tw-space-y-reverse))); + margin-bottom: calc(1.5rem * var(--tw-space-y-reverse)); +} + +.divide-y > :not([hidden]) ~ :not([hidden]) { + --tw-divide-y-reverse: 0; + border-top-width: calc(1px * calc(1 - var(--tw-divide-y-reverse))); + border-bottom-width: calc(1px * var(--tw-divide-y-reverse)); +} + +.divide-border > :not([hidden]) ~ :not([hidden]) { + --tw-divide-opacity: 1; + border-color: hsl(var(--border) / var(--tw-divide-opacity)); +} + +.overflow-auto { + overflow: auto; +} + +.overflow-hidden { + overflow: hidden; +} + +.overflow-y-auto { + overflow-y: auto; +} + +.whitespace-nowrap { + white-space: nowrap; +} + +.rounded-full { + border-radius: 9999px; +} + +.rounded-lg { + border-radius: var(--radius); +} + +.rounded-md { + border-radius: calc(var(--radius) - 2px); +} + +.rounded-sm { + border-radius: calc(var(--radius) - 4px); +} + +.border { + border-width: 1px; +} + +.border-2 { + border-width: 2px; +} + +.border-b { + border-bottom-width: 1px; +} + +.border-l { + border-left-width: 1px; +} + +.border-r { + border-right-width: 1px; +} + +.border-t { + border-top-width: 1px; +} + +.border-blue-500 { + --tw-border-opacity: 1; + border-color: rgb(59 130 246 / var(--tw-border-opacity)); +} + +.border-border { + --tw-border-opacity: 1; + border-color: hsl(var(--border) / var(--tw-border-opacity)); +} + +.border-destructive { + --tw-border-opacity: 1; + border-color: hsl(var(--destructive) / var(--tw-border-opacity)); +} + +.border-foreground { + --tw-border-opacity: 1; + border-color: hsl(var(--foreground) / var(--tw-border-opacity)); +} + +.border-input { + --tw-border-opacity: 1; + border-color: hsl(var(--input) / var(--tw-border-opacity)); +} + +.border-primary { + --tw-border-opacity: 1; + border-color: hsl(var(--primary) / var(--tw-border-opacity)); +} + +.border-transparent { + border-color: transparent; +} + +.bg-background { + --tw-bg-opacity: 1; + background-color: hsl(var(--background) / var(--tw-bg-opacity)); +} + +.bg-background\/80 { + background-color: hsl(var(--background) / 0.8); +} + +.bg-black { + --tw-bg-opacity: 1; + background-color: rgb(0 0 0 / var(--tw-bg-opacity)); +} + +.bg-card { + --tw-bg-opacity: 1; + background-color: hsl(var(--card) / var(--tw-bg-opacity)); +} + +.bg-destructive { + --tw-bg-opacity: 1; + background-color: hsl(var(--destructive) / var(--tw-bg-opacity)); +} + +.bg-destructive\/10 { + background-color: hsl(var(--destructive) / 0.1); +} + +.bg-green-500 { + --tw-bg-opacity: 1; + background-color: rgb(34 197 94 / var(--tw-bg-opacity)); +} + +.bg-muted { + --tw-bg-opacity: 1; + background-color: hsl(var(--muted) / var(--tw-bg-opacity)); +} + +.bg-muted\/50 { + background-color: hsl(var(--muted) / 0.5); +} + +.bg-neutral-200 { + --tw-bg-opacity: 1; + background-color: rgb(229 229 229 / var(--tw-bg-opacity)); +} + +.bg-popover { + --tw-bg-opacity: 1; + background-color: hsl(var(--popover) / var(--tw-bg-opacity)); +} + +.bg-primary { + --tw-bg-opacity: 1; + background-color: hsl(var(--primary) / var(--tw-bg-opacity)); +} + +.bg-primary\/90 { + background-color: hsl(var(--primary) / 0.9); +} + +.bg-red-500 { + --tw-bg-opacity: 1; + background-color: rgb(239 68 68 / var(--tw-bg-opacity)); +} + +.bg-secondary { + --tw-bg-opacity: 1; + background-color: hsl(var(--secondary) / var(--tw-bg-opacity)); +} + +.bg-opacity-50 { + --tw-bg-opacity: 0.5; +} + +.object-cover { + -o-object-fit: cover; + object-fit: cover; +} + +.p-1 { + padding: 0.25rem; +} + +.p-2 { + padding: 0.5rem; +} + +.p-4 { + padding: 1rem; +} + +.p-6 { + padding: 1.5rem; +} + +.px-0\.5 { + padding-left: 0.125rem; + padding-right: 0.125rem; +} + +.px-3 { + padding-left: 0.75rem; + padding-right: 0.75rem; +} + +.px-4 { + padding-left: 1rem; + padding-right: 1rem; +} + +.px-5 { + padding-left: 1.25rem; + padding-right: 1.25rem; +} + +.px-8 { + padding-left: 2rem; + padding-right: 2rem; +} + +.py-1 { + padding-top: 0.25rem; + padding-bottom: 0.25rem; +} + +.py-2 { + padding-top: 0.5rem; + padding-bottom: 0.5rem; +} + +.py-3 { + padding-top: 0.75rem; + padding-bottom: 0.75rem; +} + +.py-4 { + padding-top: 1rem; + padding-bottom: 1rem; +} + +.py-6 { + padding-top: 1.5rem; + padding-bottom: 1.5rem; +} + +.pb-4 { + padding-bottom: 1rem; +} + +.pt-0 { + padding-top: 0px; +} + +.pt-5 { + padding-top: 1.25rem; +} + +.text-left { + text-align: left; +} + +.text-center { + text-align: center; +} + +.text-base { + font-size: 1rem; + line-height: 1.5rem; +} + +.text-lg { + font-size: 1.125rem; + line-height: 1.75rem; +} + +.text-sm { + font-size: 0.875rem; + line-height: 1.25rem; +} + +.text-xl { + font-size: 1.25rem; + line-height: 1.75rem; +} + +.text-xs { + font-size: 0.75rem; + line-height: 1rem; +} + +.font-bold { + font-weight: 700; +} + +.font-extrabold { + font-weight: 800; +} + +.font-medium { + font-weight: 500; +} + +.font-normal { + font-weight: 400; +} + +.font-semibold { + font-weight: 600; +} + +.italic { + font-style: italic; +} + +.leading-6 { + line-height: 1.5rem; +} + +.leading-none { + line-height: 1; +} + +.tracking-tight { + letter-spacing: -0.025em; +} + +.text-accent-foreground { + --tw-text-opacity: 1; + color: hsl(var(--accent-foreground) / var(--tw-text-opacity)); +} + +.text-card-foreground { + --tw-text-opacity: 1; + color: hsl(var(--card-foreground) / var(--tw-text-opacity)); +} + +.text-destructive { + --tw-text-opacity: 1; + color: hsl(var(--destructive) / var(--tw-text-opacity)); +} + +.text-destructive-foreground { + --tw-text-opacity: 1; + color: hsl(var(--destructive-foreground) / var(--tw-text-opacity)); +} + +.text-foreground { + --tw-text-opacity: 1; + color: hsl(var(--foreground) / var(--tw-text-opacity)); +} + +.text-gray-400 { + --tw-text-opacity: 1; + color: rgb(156 163 175 / var(--tw-text-opacity)); +} + +.text-gray-600 { + --tw-text-opacity: 1; + color: rgb(75 85 99 / var(--tw-text-opacity)); +} + +.text-gray-700 { + --tw-text-opacity: 1; + color: rgb(55 65 81 / var(--tw-text-opacity)); +} + +.text-muted-foreground { + --tw-text-opacity: 1; + color: hsl(var(--muted-foreground) / var(--tw-text-opacity)); +} + +.text-popover-foreground { + --tw-text-opacity: 1; + color: hsl(var(--popover-foreground) / var(--tw-text-opacity)); +} + +.text-primary { + --tw-text-opacity: 1; + color: hsl(var(--primary) / var(--tw-text-opacity)); +} + +.text-primary-foreground { + --tw-text-opacity: 1; + color: hsl(var(--primary-foreground) / var(--tw-text-opacity)); +} + +.text-secondary-foreground { + --tw-text-opacity: 1; + color: hsl(var(--secondary-foreground) / var(--tw-text-opacity)); +} + +.underline { + text-decoration-line: underline; +} + +.underline-offset-4 { + text-underline-offset: 4px; +} + +.antialiased { + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.opacity-0 { + opacity: 0; +} + +.opacity-100 { + opacity: 1; +} + +.opacity-80 { + opacity: 0.8; +} + +.shadow { + --tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1); + --tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); +} + +.shadow-lg { + --tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1); + --tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); +} + +.shadow-sm { + --tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05); + --tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); +} + +.shadow-xl { + --tw-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1); + --tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); +} + +.outline { + outline-style: solid; +} + +.ring-1 { + --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color); + --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color); + box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000); +} + +.ring-black { + --tw-ring-opacity: 1; + --tw-ring-color: rgb(0 0 0 / var(--tw-ring-opacity)); +} + +.ring-opacity-5 { + --tw-ring-opacity: 0.05; +} + +.ring-offset-background { + --tw-ring-offset-color: hsl(var(--background) / 1); +} + +.filter { + filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow); +} + +.backdrop-blur-sm { + --tw-backdrop-blur: blur(4px); + -webkit-backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia); + backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia); +} + +.transition { + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter; + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter; + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; +} + +.transition-all { + transition-property: all; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; +} + +.transition-colors { + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; +} + +.transition-opacity { + transition-property: opacity; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; +} + +.duration-100 { + transition-duration: 100ms; +} + +.duration-150 { + transition-duration: 150ms; +} + +.duration-200 { + transition-duration: 200ms; +} + +.duration-300 { + transition-duration: 300ms; +} + +.duration-75 { + transition-duration: 75ms; +} + +.ease-in { + transition-timing-function: cubic-bezier(0.4, 0, 1, 1); +} + +.ease-in-out { + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); +} + +.ease-out { + transition-timing-function: cubic-bezier(0, 0, 0.2, 1); +} + +.\[start\:end\] { + start: end; +} + +.file\:border-0::file-selector-button { + border-width: 0px; +} + +.file\:bg-transparent::file-selector-button { + background-color: transparent; +} + +.file\:text-sm::file-selector-button { + font-size: 0.875rem; + line-height: 1.25rem; +} + +.file\:font-medium::file-selector-button { + font-weight: 500; +} + +.file\:text-foreground::file-selector-button { + --tw-text-opacity: 1; + color: hsl(var(--foreground) / var(--tw-text-opacity)); +} + +.placeholder\:text-muted-foreground::-moz-placeholder { + --tw-text-opacity: 1; + color: hsl(var(--muted-foreground) / var(--tw-text-opacity)); +} + +.placeholder\:text-muted-foreground::placeholder { + --tw-text-opacity: 1; + color: hsl(var(--muted-foreground) / var(--tw-text-opacity)); +} + +.before\:absolute::before { + content: var(--tw-content); + position: absolute; +} + +.before\:inset-0::before { + content: var(--tw-content); + inset: 0px; +} + +.before\:left-1\/2::before { + content: var(--tw-content); + left: 50%; +} + +.before\:top-1\/2::before { + content: var(--tw-content); + top: 50%; +} + +.before\:h-2::before { + content: var(--tw-content); + height: 0.5rem; +} + +.before\:w-2::before { + content: var(--tw-content); + width: 0.5rem; +} + +.before\:-translate-x-1\/2::before { + content: var(--tw-content); + --tw-translate-x: -50%; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.before\:-translate-y-1\/2::before { + content: var(--tw-content); + --tw-translate-y: -50%; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.before\:rounded-full::before { + content: var(--tw-content); + border-radius: 9999px; +} + +.before\:bg-background::before { + content: var(--tw-content); + --tw-bg-opacity: 1; + background-color: hsl(var(--background) / var(--tw-bg-opacity)); +} + +.after\:absolute::after { + content: var(--tw-content); + position: absolute; +} + +.after\:left-0\.5::after { + content: var(--tw-content); + left: 0.125rem; +} + +.after\:top-0\.5::after { + content: var(--tw-content); + top: 0.125rem; +} + +.after\:h-5::after { + content: var(--tw-content); + height: 1.25rem; +} + +.after\:w-5::after { + content: var(--tw-content); + width: 1.25rem; +} + +.after\:rounded-full::after { + content: var(--tw-content); + border-radius: 9999px; +} + +.after\:bg-muted-foreground::after { + content: var(--tw-content); + --tw-bg-opacity: 1; + background-color: hsl(var(--muted-foreground) / var(--tw-bg-opacity)); +} + +.after\:transition-all::after { + content: var(--tw-content); + transition-property: all; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; +} + +.after\:content-\[\'\'\]::after { + --tw-content: ''; + content: var(--tw-content); +} + +.checked\:border-primary:checked { + --tw-border-opacity: 1; + border-color: hsl(var(--primary) / var(--tw-border-opacity)); +} + +.checked\:bg-primary:checked { + --tw-bg-opacity: 1; + background-color: hsl(var(--primary) / var(--tw-bg-opacity)); +} + +.checked\:before\:visible:checked::before { + content: var(--tw-content); + visibility: visible; +} + +.checked\:before\:bg-primary:checked::before { + content: var(--tw-content); + --tw-bg-opacity: 1; + background-color: hsl(var(--primary) / var(--tw-bg-opacity)); +} + +.hover\:bg-accent:hover { + --tw-bg-opacity: 1; + background-color: hsl(var(--accent) / var(--tw-bg-opacity)); +} + +.hover\:bg-blue-500:hover { + --tw-bg-opacity: 1; + background-color: rgb(59 130 246 / var(--tw-bg-opacity)); +} + +.hover\:bg-destructive\/90:hover { + background-color: hsl(var(--destructive) / 0.9); +} + +.hover\:bg-gray-100:hover { + --tw-bg-opacity: 1; + background-color: rgb(243 244 246 / var(--tw-bg-opacity)); +} + +.hover\:bg-muted:hover { + --tw-bg-opacity: 1; + background-color: hsl(var(--muted) / var(--tw-bg-opacity)); +} + +.hover\:bg-primary\/90:hover { + background-color: hsl(var(--primary) / 0.9); +} + +.hover\:bg-secondary\/80:hover { + background-color: hsl(var(--secondary) / 0.8); +} + +.hover\:text-accent-foreground:hover { + --tw-text-opacity: 1; + color: hsl(var(--accent-foreground) / var(--tw-text-opacity)); +} + +.hover\:text-foreground:hover { + --tw-text-opacity: 1; + color: hsl(var(--foreground) / var(--tw-text-opacity)); +} + +.hover\:text-gray-500:hover { + --tw-text-opacity: 1; + color: rgb(107 114 128 / var(--tw-text-opacity)); +} + +.hover\:text-primary\/80:hover { + color: hsl(var(--primary) / 0.8); +} + +.hover\:underline:hover { + text-decoration-line: underline; +} + +.hover\:opacity-100:hover { + opacity: 1; +} + +.focus\:outline-none:focus { + outline: 2px solid transparent; + outline-offset: 2px; +} + +.focus\:outline:focus { + outline-style: solid; +} + +.focus\:outline-2:focus { + outline-width: 2px; +} + +.focus\:outline-offset-2:focus { + outline-offset: 2px; +} + +.focus\:outline-ring:focus { + outline-color: hsl(var(--ring) / 1); +} + +.focus\:ring-2:focus { + --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color); + --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color); + box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000); +} + +.focus\:ring-inset:focus { + --tw-ring-inset: inset; +} + +.focus\:ring-indigo-500:focus { + --tw-ring-opacity: 1; + --tw-ring-color: rgb(99 102 241 / var(--tw-ring-opacity)); +} + +.focus\:ring-ring:focus { + --tw-ring-opacity: 1; + --tw-ring-color: hsl(var(--ring) / var(--tw-ring-opacity)); +} + +.focus\:ring-offset-2:focus { + --tw-ring-offset-width: 2px; +} + +.checked\:focus\:outline-primary:focus:checked { + outline-color: hsl(var(--primary) / 1); +} + +.focus-visible\:outline-none:focus-visible { + outline: 2px solid transparent; + outline-offset: 2px; +} + +.focus-visible\:ring-2:focus-visible { + --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color); + --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color); + box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000); +} + +.focus-visible\:ring-ring:focus-visible { + --tw-ring-opacity: 1; + --tw-ring-color: hsl(var(--ring) / var(--tw-ring-opacity)); +} + +.focus-visible\:ring-offset-2:focus-visible { + --tw-ring-offset-width: 2px; +} + +.focus-visible\:ring-offset-background:focus-visible { + --tw-ring-offset-color: hsl(var(--background) / 1); +} + +.active\:outline-offset-0:active { + outline-offset: 0px; +} + +.disabled\:pointer-events-none:disabled { + pointer-events: none; +} + +.disabled\:cursor-not-allowed:disabled { + cursor: not-allowed; +} + +.disabled\:opacity-50:disabled { + opacity: 0.5; +} + +.group:hover .group-hover\:block { + display: block; +} + +.group:hover .group-hover\:translate-x-0 { + --tw-translate-x: 0px; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.group:hover .group-hover\:text-foreground { + --tw-text-opacity: 1; + color: hsl(var(--foreground) / var(--tw-text-opacity)); +} + +.group:hover .group-hover\:opacity-100 { + opacity: 1; +} + +.peer:checked ~ .peer-checked\:visible { + visibility: visible; +} + +.peer:checked ~ .peer-checked\:bg-primary { + --tw-bg-opacity: 1; + background-color: hsl(var(--primary) / var(--tw-bg-opacity)); +} + +.peer:checked ~ .peer-checked\:text-foreground { + --tw-text-opacity: 1; + color: hsl(var(--foreground) / var(--tw-text-opacity)); +} + +.peer:checked ~ .peer-checked\:after\:translate-x-\[16px\]::after { + content: var(--tw-content); + --tw-translate-x: 16px; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.peer:checked ~ .peer-checked\:after\:bg-secondary::after { + content: var(--tw-content); + --tw-bg-opacity: 1; + background-color: hsl(var(--secondary) / var(--tw-bg-opacity)); +} + +.peer:disabled ~ .peer-disabled\:cursor-not-allowed { + cursor: not-allowed; +} + +.peer:disabled ~ .peer-disabled\:opacity-50 { + opacity: 0.5; +} + +.peer:disabled ~ .peer-disabled\:opacity-70 { + opacity: 0.7; +} + +.dark\:text-gray-200:is(.dark *) { + --tw-text-opacity: 1; + color: rgb(229 231 235 / var(--tw-text-opacity)); +} + +.dark\:file\:text-foreground:is(.dark *)::file-selector-button { + --tw-text-opacity: 1; + color: hsl(var(--foreground) / var(--tw-text-opacity)); +} + +.dark\:hover\:bg-gray-700:hover:is(.dark *) { + --tw-bg-opacity: 1; + background-color: rgb(55 65 81 / var(--tw-bg-opacity)); +} + +@media (min-width: 640px) { + .sm\:my-8 { + margin-top: 2rem; + margin-bottom: 2rem; + } + + .sm\:flex { + display: flex; + } + + .sm\:h-1\/2 { + height: 50%; + } + + .sm\:max-w-\[70\%\] { + max-width: 70%; + } + + .sm\:flex-row-reverse { + flex-direction: row-reverse; + } + + .sm\:p-6 { + padding: 1.5rem; + } + + .sm\:px-6 { + padding-left: 1.5rem; + padding-right: 1.5rem; + } + + .sm\:pb-4 { + padding-bottom: 1rem; + } +} + +@media (min-width: 768px) { + .md\:flex { + display: flex; + } + + .md\:h-6 { + height: 1.5rem; + } + + .md\:w-1\/2 { + width: 50%; + } + + .md\:text-sm { + font-size: 0.875rem; + line-height: 1.25rem; + } +} + +@media (min-width: 1024px) { + .lg\:hidden { + display: none; + } + + .lg\:w-1\/3 { + width: 33.333333%; + } +} + +.\[\&\:has\(\:disabled\)\]\:cursor-not-allowed:has(:disabled) { + cursor: not-allowed; +} + +.\[\&\:has\(\:disabled\)\]\:opacity-50:has(:disabled) { + opacity: 0.5; +} + +.\[\&\:has\(input\:checked\)\]\:text-foreground:has(input:checked) { + --tw-text-opacity: 1; + color: hsl(var(--foreground) / var(--tw-text-opacity)); +} + +.\[\&\:has\(input\:disabled\)\]\:cursor-not-allowed:has(input:disabled) { + cursor: not-allowed; +} + +.\[\&\:has\(input\:disabled\)\]\:opacity-50:has(input:disabled) { + opacity: 0.5; +} + +.\[\&\:has\(svg\)\]\:pl-11:has(svg) { + padding-left: 2.75rem; +} + +.\[\&\>svg\+div\]\:translate-y-\[-3px\]>svg+div { + --tw-translate-y: -3px; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.\[\&\>svg\]\:absolute>svg { + position: absolute; +} + +.\[\&\>svg\]\:left-4>svg { + left: 1rem; +} + +.\[\&\>svg\]\:top-4>svg { + top: 1rem; +} + +.\[\&\[aria-expanded\=true\]\>svg\]\:rotate-180[aria-expanded=true]>svg { + --tw-rotate: 180deg; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.\[\&_p\]\:leading-relaxed p { + line-height: 1.625; +} + +================ +File: pkg/utils/utils.go +================ +package utils + +import ( + "fmt" + + "github.com/a-h/templ" + + twmerge "github.com/Oudwins/tailwind-merge-go" +) + +// TwMerge combines Tailwind classes and handles conflicts. +// Later classes override earlier ones with the same base. +// Example: "bg-red-500 hover:bg-blue-500", "bg-green-500" → "hover:bg-blue-500 bg-green-500" +func TwMerge(classes ...string) string { + return twmerge.Merge(classes...) +} + +// CSS returns a link tag for the Goilerplate CSS +// If no branch is specified, it defaults to 'main' +func CSS(branch string) templ.Component { + if branch == "" { + branch = "main" + } + + cssURL := fmt.Sprintf("https://cdn.jsdelivr.net/gh/axzilla/goilerplate@%s/pkg/styles/goilerplate.css", branch) + return templ.Raw(fmt.Sprintf(``, cssURL)) +} + +// Alpine returns script tags for Alpine.js +func AlpineJS() templ.Component { + return templ.Raw(` + + + `) +} + +================ +File: .dockerignore +================ +# Ignore node_modules folder +node_modules + +# Ignore logs +logs +*.log +npm-debug.log* + +# Ignore dotenv environment variable files +.env + +# Ignore local development configuration files +config/local.yml + +# Ignore temporary files and directories +tmp/ +temp/ +*.tmp + +# Ignore build and cache directories +build/ +dist/ +.cache/ + +# Ignore OS generated files +.DS_Store +Thumbs.db + +# Ignore version control directories and files +.git +.gitignore +.gitmodules +.hg +.hgignore +.hgsubstate +.svn +.cvsignore + +# Ignore Python files +*.pyc +*.pyo +__pycache__/ + +# Ignore compiled source files +*.o +*.obj +*.dll +*.exe +*.out + +# Ignore images and other binary files +*.png +*.jpg +*.jpeg +*.gif +*.bmp +*.tiff +*.ico + +# Ignore compressed files +*.zip +*.tar.gz +*.rar +*.7z +*.bz2 + +# Ignore various IDE project files +.vscode/ +.idea/ +*.suo +*.user +*.userossc +*.sln.docstates +.project +.classpath +.settings/ + +# Ignore documentation files +*.md +*.pdf + +# Ignore build output files +*.war +*.jar +*.ear + +# Ignore Kubernetes and Docker Compose files +k8s/ +docker-compose.yml +docker-compose.override.yml + +# Ignore other sensitive files +*.pem +*.key +*.crt +*.kdb +*.jks + +# Ignore IntelliJ IDEA files +*.iml +*.iws +.idea/ + +# Ignore JetBrains Rider files +*.sln.iml +.idea/ + +# Ignore WebStorm files +.idea/ + +# Ignore Visual Studio Code files +.vscode/ + +# Ignore SASS cache files +.sass-cache/ + +# Ignore Bower files +.bower/ + +# Ignore Gulp files +.gulp/ + +# Ignore Grunt files +.grunt/ + +# Ignore Yeoman files +.yeoman/ + +================ +File: .env.example +================ +GO_ENV=development + +================ +File: .gitignore +================ +# exlude generated files but not for the pkg folder +internals/**/*_templ.go +internals/**/*_templ.txt + +# exclude .txt files because they are not needed as a go package but the .go files are +pkg/**/*_templ.txt + +.DS_Store +bin +node_modules +tmp +.env + +================ +File: CHEATSHEET.md +================ +# Goilerplate Commit & Release Cheatsheet + +## Commit Message Format + +``: `` + +## Types + +- `feat`: New feature or component +- `fix`: Bug fix +- `docs`: Documentation changes +- `style`: Changes that do not affect the meaning of the code (white-space, formatting, etc) +- `refactor`: Code change that neither fixes a bug nor adds a feature +- `perf`: Code change that improves performance +- `test`: Adding missing tests or correcting existing tests +- `chore`: Changes to the build process or auxiliary tools and libraries + +## Examples + +- `feat: add Button component` +- `fix: correct Card component padding on mobile` +- `refactor: simplify Modal component logic` + +## Breaking Changes + +Add `!` after the type for breaking changes: + +- `feat!: redesign Form component API` + +## Versioning Strategy (0.x.y) + +- 0: Remains 0 until the first stable version (1.0.0) +- x: For major changes or feature sets (e.g., 20) +- y: For minor changes, bugfixes, and incremental updates + +## Version Increments + +- Increase second number (x) for: + - New major features + - Significant API or functionality changes +- Increase third number (y) for: + - Bugfixes + - Small feature additions + - Documentation changes + - Performance optimizations + - Other minor changes + +## Release Process + +1. Commit changes: + + ``` + git add . + git commit -m "feat: implement XYZ feature" + ``` + +2. Tag and push version: + + ``` + git tag -a v0.20.2 -m "Release v0.20.2" + git push origin main --tags + ``` + +3. Create GitHub Release: + - Go to GitHub > Releases > "Draft a new release" + - Select the created tag + - Title: "Release v0.20.2" + - Description: Brief summary of main changes + - Publish the release + +## Go Module Usage + +- Install latest version: + ``` + go get github.com/axzilla/goilerplate@latest + ``` +- Install specific version: + ``` + go get github.com/axzilla/goilerplate@v0.20.2 + ``` +- Install development version: + ``` + go get github.com/axzilla/goilerplate@main + ``` + +Remind users to run `go mod tidy` after changes. + +## Transition to 1.0.0 + +Switch to 1.0.0 when the project: + +- Has a stable API +- Is sufficiently tested +- Is ready for production environments +- Offers a solid feature base + +================ +File: CONTRIBUTING.md +================ +# Contributing to Goilerplate + +First off, thank you for considering contributing to Goilerplate! We're excited to have you join our community. + +## Our Vision and Your Contributions + +Goilerplate is an open-source project that aims to provide value to the Go community. We want to be transparent about our long-term vision: + +1. We may explore opportunities to monetize aspects of Goilerplate or offer premium services related to it in the future. +2. All contributions to this repository are subject to the MIT License, which allows for commercial use. +3. By contributing to Goilerplate, you agree that your contributions may be used in both open-source and potential future commercial aspects of the project. +4. We value every contribution and will always strive to maintain a strong, open-source core that benefits the entire community. + +We believe this approach allows us to sustainably develop and maintain Goilerplate while keeping it open and accessible to all. If you have any questions or concerns about this, please reach out to us before contributing. + +## How Can I Contribute? + +### Reporting Bugs + +- Use a clear and descriptive title for the issue to identify the problem. +- Describe the exact steps which reproduce the problem in as many details as possible. +- Provide specific examples to demonstrate the steps. + +### Suggesting Enhancements + +- Use a clear and descriptive title for the issue to identify the suggestion. +- Provide a step-by-step description of the suggested enhancement in as many details as possible. +- Explain why this enhancement would be useful to most Goilerplate users. + +### Pull Requests + +- Fill in the required template +- Do not include issue numbers in the PR title +- Follow the [Go style guide](https://golang.org/doc/effective_go.html) +- End all files with a newline +- Avoid platform-dependent code + +## Style Guides + +### Git Commit Messages + +- Use the present tense ("Add feature" not "Added feature") +- Use the imperative mood ("Move cursor to..." not "Moves cursor to...") +- Limit the first line to 72 characters or less + +### Go Style Guide + +Follow the official Go style guide and common practices in the Go community. + +## Additional Notes + +### Issue and Pull Request Labels + +This section lists the labels we use to help us track and manage issues and pull requests. + +- `bug` - Issues for bugs in the code +- `enhancement` - Issues for new features or improvements +- `documentation` - Issues related to documentation +- `good first issue` - Good for newcomers + +## Recognition + +We're committed to giving proper credit and recognition to all contributors. Your contributions, whether they're improvements to documentation, bug fixes, or new features, are invaluable to the growth and success of Goilerplate. + +Thank you for contributing to Goilerplate and helping make it a great tool for the Go community! + +================ +File: Dockerfile +================ +# Build-Stage +FROM golang:1.22-alpine AS build +WORKDIR /app + +# Copy the source code +COPY . . + +# Install templ +RUN go install github.com/a-h/templ/cmd/templ@latest + +# Generate templ files +RUN templ generate + +# Install build dependencies +RUN apk add --no-cache gcc musl-dev + +# Build the application +RUN CGO_ENABLED=1 GOOS=linux go build -o main ./cmd/server/main.go + +# Deploy-Stage +FROM alpine:3.20.2 +WORKDIR /app + +# Install ca-certificates +RUN apk add --no-cache ca-certificates + +# Set environment variable for runtime +ENV GO_ENV=production + +# Copy the binary from the build stage +COPY --from=build /app/main . + +# Expose the port your application runs on +EXPOSE 8090 + +# Command to run the application +CMD ["./main"] + +================ +File: go.mod +================ +module github.com/axzilla/goilerplate + +go 1.22.4 + +require ( + github.com/Oudwins/tailwind-merge-go v0.2.0 + github.com/a-h/templ v0.2.778 + github.com/joho/godotenv v1.5.1 +) + +================ +File: go.sum +================ +github.com/Oudwins/tailwind-merge-go v0.2.0 h1:rtVHgYmLwwae4P+K6//ceRuUdyz3Bny6fo4664fOEmo= +github.com/Oudwins/tailwind-merge-go v0.2.0/go.mod h1:kkZodgOPvZQ8f7SIrlWkG/w1g9JTbtnptnePIh3V72U= +github.com/a-h/templ v0.2.778 h1:VzhOuvWECrwOec4790lcLlZpP4Iptt5Q4K9aFxQmtaM= +github.com/a-h/templ v0.2.778/go.mod h1:lq48JXoUvuQrU0VThrK31yFwdRjTCnIE5bcPCM9IP1w= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= +github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= + +================ +File: LICENSE +================ +MIT License + +Copyright (c) 2023 Axel Adrian + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +================ +File: Makefile +================ +# Dev Tools +templ: + templ generate --watch --proxy="http://localhost:8090" --open-browser=false -v + +server: + air \ + --build.cmd "go build -o tmp/bin/main ./cmd/server" \ + --build.bin "tmp/bin/main" \ + --build.delay "100" \ + --build.exclude_dir "node_modules" \ + --build.include_ext "go" \ + --build.stop_on_error "false" \ + --misc.clean_on_exit true + +tailwind-app: + npx tailwindcss -i ./assets/css/input.css -o ./assets/css/output.css --watch + +tailwind-goilerplate: + npx tailwindcss -c ./tailwind.config.lib.js -i ./assets/css/input.css -o ./pkg/styles/goilerplate.css --watch + +dev: + make -j4 templ server tailwind-app tailwind-goilerplate + +debug: + make -j3 templ tailwind-app tailwind-goilerplate + +generate-icons: + go run cmd/icongen/main.go + +================ +File: README.md +================ +# Goilerplate + +Modern UI Components for Go & Templ + +Goilerplate Logo + +## About + +Goilerplate is a growing library of modern UI components designed specifically for Go and Templ. It leverages Alpine.js for enhanced interactivity and Tailwind CSS for effortless styling. Whether you're building a small website or a large web application, Goilerplate provides the tools you need to create sleek, responsive interfaces with ease. + +## Features + +- **Go-native Implementation**: Optimized for Go developers, seamlessly integrating with Go backends. +- **Templ-first Design**: Leverages the full power of Templ for type-safe, high-performance templating. +- **Server-Side Rendering (SSR) Focus**: Excellent performance and SEO benefits out of the box. +- **Alpine.js Integration**: Enhanced client-side interactivity when needed. +- **Tailwind CSS Styling**: Modern, utility-first styling that's highly customizable. +- **Accessible Components**: Built with accessibility in mind, following WCAG guidelines. +- **TypeSafe**: Utilizing Go's type system for robust, error-resistant development. + +## Getting Started + +There are two main ways to use Goilerplate in your projects: + +1. **Use as a Package Library** + + Install Goilerplate as a Go package: + + ``` + go get github.com/axzilla/goilerplate + ``` + + Then import and use components in your Templ files: + + ```go + import "github.com/axzilla/goilerplate/pkg/components" + + // In your Templ files + @components.Button(components.ButtonProps{Text: "Click me"}) + ``` + +2. **Copy Components to Your Codebase** + + Visit our [components documentation](https://goilerplate.com/docs/components) to find and copy the components you need directly into your project. + +You can also mix and match these approaches based on your project needs. + +For a quick start, check out our [Goilerplate quickstart](https://github.com/axzilla/goilerplate-quickstart) template, which provides a pre-configured setup using Goilerplate as a package library. + +For detailed setup instructions and examples, visit our [how to use guide](https://goilerplate.com/docs/how-to-use). + +## Components + +Explore our growing list of components in the [components documentation](https://goilerplate.com/docs/components). Each component comes with usage examples and code snippets. + +## Inspiration + +Goilerplate draws inspiration from several popular UI libraries and frameworks: + +- [shadcn/ui](https://ui.shadcn.com/) +- [Pines UI](https://devdojo.com/pines) +- [daisyUI](https://daisyui.com/) + +We're exploring whether to make Goilerplate a strict port of shadcn/ui or to create a unique blend of various inspirations. The project is still evolving, and community feedback will play a crucial role in shaping its direction. + +## Current Status + +- **Heavy Development**: The project is under active development. Expect frequent updates and potential breaking changes until we reach a stable version. +- Actively growing component library +- Regular updates and bug fixes +- Continuous development based on community feedback + +## Changelog + +See [releases](https://github.com/axzilla/goilerplate/releases) for a detailed list of changes in each version. + +## Contributing + +We welcome contributions from the community! Whether it's adding new components, improving existing ones, or enhancing documentation, your input is valuable. Please check our [contributing guidelines](CONTRIBUTING.md) for more information on how to get involved. + +## Feedback + +Your feedback is crucial in shaping the future of Goilerplate. If you have suggestions, feature requests, or encounter any issues, please [open an issue](https://github.com/axzilla/goilerplate/issues) on our GitHub repository or reach out to us through our website. + +## License + +Goilerplate is open-source software licensed under the [MIT license](LICENSE). + +## Support + +For support, questions, or discussions, please [open an issue](https://github.com/axzilla/goilerplate/issues) on our GitHub repository. + +--- + +Built with ❤️ by the Go community, for the Go community. + +================ +File: tailwind.config.js +================ +import { fontFamily } from "tailwindcss/defaultTheme"; + +/** @type {import('tailwindcss').Config} */ +const config = { + darkMode: ["class"], + content: ["./**/*.html", "./**/*.templ", "./**/*.go"], + safelist: ["dark"], + theme: { + container: { + center: true, + padding: "2rem", + screens: { + "2xl": "1400px", + }, + }, + extend: { + colors: { + border: "hsl(var(--border) / )", + input: "hsl(var(--input) / )", + ring: "hsl(var(--ring) / )", + background: "hsl(var(--background) / )", + foreground: "hsl(var(--foreground) / )", + primary: { + DEFAULT: "hsl(var(--primary) / )", + foreground: "hsl(var(--primary-foreground) / )", + }, + secondary: { + DEFAULT: "hsl(var(--secondary) / )", + foreground: "hsl(var(--secondary-foreground) / )", + }, + destructive: { + DEFAULT: "hsl(var(--destructive) / )", + foreground: "hsl(var(--destructive-foreground) / )", + }, + muted: { + DEFAULT: "hsl(var(--muted) / )", + foreground: "hsl(var(--muted-foreground) / )", + }, + accent: { + DEFAULT: "hsl(var(--accent) / )", + foreground: "hsl(var(--accent-foreground) / )", + }, + popover: { + DEFAULT: "hsl(var(--popover) / )", + foreground: "hsl(var(--popover-foreground) / )", + }, + card: { + DEFAULT: "hsl(var(--card) / )", + foreground: "hsl(var(--card-foreground) / )", + }, + }, + borderRadius: { + lg: "var(--radius)", + md: "calc(var(--radius) - 2px)", + sm: "calc(var(--radius) - 4px)", + }, + fontFamily: { + sans: ["Inter", ...fontFamily.sans], + }, + }, + }, +}; + +export default config; + +================ +File: tailwind.config.lib.js +================ +const baseConfig = require("./tailwind.config.js"); + +module.exports = { + ...baseConfig, + content: ["./pkg/**/*.templ", "./pkg/**/*.go"], +}; From 5224ac91643058d2eeb9140a7b74b1ddaeae8ac8 Mon Sep 17 00:00:00 2001 From: axzilla Date: Thu, 21 Nov 2024 17:48:46 +0700 Subject: [PATCH 12/17] change: slider component WIP --- assets/css/output.css | 82 +++++++++ cmd/server/main.go | 1 + internals/shared/menudata.go | 4 + internals/ui/pages/slider.templ | 39 +++++ internals/ui/showcase/slider.templ | 79 +++++++++ pkg/components/slider.templ | 94 +++++++++++ pkg/components/slider_templ.go | 263 +++++++++++++++++++++++++++++ pkg/styles/goilerplate.css | 82 +++++++++ 8 files changed, 644 insertions(+) create mode 100644 internals/ui/pages/slider.templ create mode 100644 internals/ui/showcase/slider.templ create mode 100644 pkg/components/slider.templ create mode 100644 pkg/components/slider_templ.go diff --git a/assets/css/output.css b/assets/css/output.css index e0d4855..e0116b5 100644 --- a/assets/css/output.css +++ b/assets/css/output.css @@ -890,6 +890,10 @@ body { height: 4rem; } +.h-2 { + height: 0.5rem; +} + .h-24 { height: 6rem; } @@ -1476,6 +1480,11 @@ body { background-color: rgb(255 255 255 / var(--tw-bg-opacity)); } +.bg-gray-200 { + --tw-bg-opacity: 1; + background-color: rgb(229 231 235 / var(--tw-bg-opacity)); +} + .bg-opacity-50 { --tw-bg-opacity: 0.5; } @@ -2492,6 +2501,79 @@ body { } } +.\[\&\:\:-moz-range-thumb\]\:h-4::-moz-range-thumb { + height: 1rem; +} + +.\[\&\:\:-moz-range-thumb\]\:w-4::-moz-range-thumb { + width: 1rem; +} + +.\[\&\:\:-moz-range-thumb\]\:cursor-pointer::-moz-range-thumb { + cursor: pointer; +} + +.\[\&\:\:-moz-range-thumb\]\:rounded-full::-moz-range-thumb { + border-radius: 9999px; +} + +.\[\&\:\:-moz-range-thumb\]\:border-0::-moz-range-thumb { + border-width: 0px; +} + +.\[\&\:\:-moz-range-thumb\]\:bg-primary::-moz-range-thumb { + --tw-bg-opacity: 1; + background-color: hsl(var(--primary) / var(--tw-bg-opacity)); +} + +.\[\&\:\:-moz-range-thumb\]\:transition-colors::-moz-range-thumb { + -moz-transition-property: color, background-color, border-color, text-decoration-color, fill, stroke; + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; +} + +.\[\&\:\:-moz-range-thumb\]\:hover\:bg-primary\/90:hover::-moz-range-thumb { + background-color: hsl(var(--primary) / 0.9); +} + +.\[\&\:\:-webkit-slider-thumb\]\:h-4::-webkit-slider-thumb { + height: 1rem; +} + +.\[\&\:\:-webkit-slider-thumb\]\:w-4::-webkit-slider-thumb { + width: 1rem; +} + +.\[\&\:\:-webkit-slider-thumb\]\:cursor-pointer::-webkit-slider-thumb { + cursor: pointer; +} + +.\[\&\:\:-webkit-slider-thumb\]\:appearance-none::-webkit-slider-thumb { + -webkit-appearance: none; + appearance: none; +} + +.\[\&\:\:-webkit-slider-thumb\]\:rounded-full::-webkit-slider-thumb { + border-radius: 9999px; +} + +.\[\&\:\:-webkit-slider-thumb\]\:bg-primary::-webkit-slider-thumb { + --tw-bg-opacity: 1; + background-color: hsl(var(--primary) / var(--tw-bg-opacity)); +} + +.\[\&\:\:-webkit-slider-thumb\]\:transition-colors::-webkit-slider-thumb { + -webkit-transition-property: color, background-color, border-color, text-decoration-color, fill, stroke; + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; +} + +.\[\&\:\:-webkit-slider-thumb\]\:hover\:bg-primary\/90:hover::-webkit-slider-thumb { + background-color: hsl(var(--primary) / 0.9); +} + .\[\&\:has\(\:disabled\)\]\:cursor-not-allowed:has(:disabled) { cursor: not-allowed; } diff --git a/cmd/server/main.go b/cmd/server/main.go index 936349f..94aa630 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -38,6 +38,7 @@ func main() { mux.Handle("GET /docs/components/radio-group", templ.Handler(pages.RadioGroup())) mux.Handle("GET /docs/components/select", templ.Handler(pages.Select())) mux.Handle("GET /docs/components/sheet", templ.Handler(pages.Sheet())) + mux.Handle("GET /docs/components/slider", templ.Handler(pages.Slider())) mux.Handle("GET /docs/components/tabs", templ.Handler(pages.Tabs())) mux.Handle("GET /docs/components/textarea", templ.Handler(pages.Textarea())) mux.Handle("GET /docs/components/toggle", templ.Handler(pages.Toggle())) diff --git a/internals/shared/menudata.go b/internals/shared/menudata.go index 5e8c81f..f013c3a 100644 --- a/internals/shared/menudata.go +++ b/internals/shared/menudata.go @@ -94,6 +94,10 @@ var Sections = []Section{ Text: "Sheet", Href: "/docs/components/sheet", }, + { + Text: "Slider", + Href: "/docs/components/slider", + }, { Text: "Tabs", Href: "/docs/components/tabs", diff --git a/internals/ui/pages/slider.templ b/internals/ui/pages/slider.templ new file mode 100644 index 0000000..7c187d2 --- /dev/null +++ b/internals/ui/pages/slider.templ @@ -0,0 +1,39 @@ +package pages + +import ( + "github.com/axzilla/goilerplate/internals/ui/layouts" + "github.com/axzilla/goilerplate/internals/ui/showcase" + "github.com/axzilla/goilerplate/pkg/components" +) + +templ Slider() { + @layouts.DocsLayout() { +
+
+

Slider

+

An input where the user selects a value from within a given range.

+
+ @components.Tabs(components.TabsProps{ + Tabs: []components.Tab{ + { + ID: "preview", + Title: "Preview", + Content: showcase.SliderShowcase(), + }, + { + ID: "code", + Title: "Code", + Content: CodeSnippetFromEmbedded("slider.templ", "go", showcase.TemplFiles), + }, + { + ID: "component", + Title: "Component", + Content: CodeSnippetFromEmbedded("slider.templ", "go", components.TemplFiles), + }, + }, + TabsContainerClass: "md:w-1/2", + ContentContainerClass: "w-full", + }) +
+ } +} diff --git a/internals/ui/showcase/slider.templ b/internals/ui/showcase/slider.templ new file mode 100644 index 0000000..01b731f --- /dev/null +++ b/internals/ui/showcase/slider.templ @@ -0,0 +1,79 @@ +// internals/ui/showcase/slider.templ + +package showcase + +import "github.com/axzilla/goilerplate/pkg/components" + +templ SliderShowcase() { +
+
+
+

Default Slider

+ @components.Slider(components.SliderProps{ + ID: "default", + Name: "default", + Label: "Volume", + Value: 50, + Min: 0, + Max: 100, + Step: 1, + ShowValue: true, + Attributes: templ.Attributes{"x-ref": "text"}, + }) +
+
+

With Label

+ @components.Slider(components.SliderProps{ + ID: "with-label", + Name: "with-label", + Label: "Volume", + Value: 75, + Min: 0, + Max: 100, + Step: 1, + ShowValue: true, + ValueFormat: "%d%", + }) +
+
+

Temperature Range

+ @components.Slider(components.SliderProps{ + ID: "temperature", + Name: "temperature", + Label: "Temperature", + Value: 23, + Min: -20, + Max: 40, + Step: 1, + ShowValue: true, + ValueFormat: "%d°C", + }) +
+
+

Steps

+ @components.Slider(components.SliderProps{ + ID: "steps", + Name: "steps", + Label: "Zoom Level", + Value: 100, + Min: 0, + Max: 200, + Step: 25, + ShowValue: true, + ValueFormat: "%d%", + }) +
+
+

Disabled

+ @components.Slider(components.SliderProps{ + ID: "disabled", + Name: "disabled", + Label: "Disabled Slider", + Value: 30, + ShowValue: true, + Disabled: true, + }) +
+
+
+} diff --git a/pkg/components/slider.templ b/pkg/components/slider.templ new file mode 100644 index 0000000..a0be316 --- /dev/null +++ b/pkg/components/slider.templ @@ -0,0 +1,94 @@ +// pkg/components/slider.templ + +package components + +import ( + "fmt" + "github.com/axzilla/goilerplate/pkg/utils" +) + +type SliderProps struct { + // ID is the unique identifier for the slider + ID string + + // Name is the name attribute for the slider + Name string + + // Min is the minimum value of the slider + Min int + + // Max is the maximum value of the slider + Max int + + // Step is the increment between values + Step int + + // Value is the initial value of the slider + Value int + + // Label displays a label above the slider + Label string + + // ShowValue determines if the current value should be displayed + ShowValue bool + + // ValueFormat is an optional format string for the displayed value (e.g. "%d°C") + ValueFormat string + + // Class allows adding custom CSS classes + Class string + + // Disabled determines if the slider is interactive + Disabled bool + + // Attributes allows passing additional HTML attributes + Attributes templ.Attributes +} + +templ Slider(props SliderProps) { +
+ if props.Label != "" || props.ShowValue { +
+ if props.Label != "" { + + } + if props.ShowValue { + + } +
+ } + +
+} diff --git a/pkg/components/slider_templ.go b/pkg/components/slider_templ.go new file mode 100644 index 0000000..acf25e8 --- /dev/null +++ b/pkg/components/slider_templ.go @@ -0,0 +1,263 @@ +// Code generated by templ - DO NOT EDIT. + +// templ: version: v0.2.778 +// pkg/components/slider.templ + +package components + +//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 ( + "fmt" + "github.com/axzilla/goilerplate/pkg/utils" +) + +type SliderProps struct { + // ID is the unique identifier for the slider + ID string + + // Name is the name attribute for the slider + Name string + + // Min is the minimum value of the slider + Min int + + // Max is the maximum value of the slider + Max int + + // Step is the increment between values + Step int + + // Value is the initial value of the slider + Value int + + // Label displays a label above the slider + Label string + + // ShowValue determines if the current value should be displayed + ShowValue bool + + // ValueFormat is an optional format string for the displayed value (e.g. "%d°C") + ValueFormat string + + // Class allows adding custom CSS classes + Class string + + // Disabled determines if the slider is interactive + Disabled bool + + // Attributes allows passing additional HTML attributes + Attributes templ.Attributes +} + +func Slider(props SliderProps) 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 = templ_7745c5c3_Buffer.WriteString("
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if props.Label != "" || props.ShowValue { + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if props.Label != "" { + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + if props.ShowValue { + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + var templ_7745c5c3_Var5 = []any{utils.TwMerge( + "w-full h-2 rounded-full bg-secondary appearance-none cursor-pointer", + "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2", + "[&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:w-4 [&::-webkit-slider-thumb]:h-4", + "[&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:bg-primary", + "[&::-webkit-slider-thumb]:hover:bg-primary/90", + "[&::-moz-range-thumb]:w-4 [&::-moz-range-thumb]:h-4 [&::-moz-range-thumb]:border-0", + "[&::-moz-range-thumb]:rounded-full [&::-moz-range-thumb]:bg-primary", + "[&::-moz-range-thumb]:hover:bg-primary/90", + "disabled:opacity-50 disabled:cursor-not-allowed", + props.Class, + )} + templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var5...) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) +} + +var _ = templruntime.GeneratedTemplate diff --git a/pkg/styles/goilerplate.css b/pkg/styles/goilerplate.css index 6a5f312..ab73d03 100644 --- a/pkg/styles/goilerplate.css +++ b/pkg/styles/goilerplate.css @@ -858,6 +858,10 @@ body { height: 4rem; } +.h-2 { + height: 0.5rem; +} + .h-4 { height: 1rem; } @@ -1297,6 +1301,11 @@ body { background-color: hsl(var(--secondary) / var(--tw-bg-opacity)); } +.bg-gray-200 { + --tw-bg-opacity: 1; + background-color: rgb(229 231 235 / var(--tw-bg-opacity)); +} + .bg-opacity-50 { --tw-bg-opacity: 0.5; } @@ -2100,6 +2109,79 @@ body { } } +.\[\&\:\:-moz-range-thumb\]\:h-4::-moz-range-thumb { + height: 1rem; +} + +.\[\&\:\:-moz-range-thumb\]\:w-4::-moz-range-thumb { + width: 1rem; +} + +.\[\&\:\:-moz-range-thumb\]\:cursor-pointer::-moz-range-thumb { + cursor: pointer; +} + +.\[\&\:\:-moz-range-thumb\]\:rounded-full::-moz-range-thumb { + border-radius: 9999px; +} + +.\[\&\:\:-moz-range-thumb\]\:border-0::-moz-range-thumb { + border-width: 0px; +} + +.\[\&\:\:-moz-range-thumb\]\:bg-primary::-moz-range-thumb { + --tw-bg-opacity: 1; + background-color: hsl(var(--primary) / var(--tw-bg-opacity)); +} + +.\[\&\:\:-moz-range-thumb\]\:transition-colors::-moz-range-thumb { + -moz-transition-property: color, background-color, border-color, text-decoration-color, fill, stroke; + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; +} + +.\[\&\:\:-moz-range-thumb\]\:hover\:bg-primary\/90:hover::-moz-range-thumb { + background-color: hsl(var(--primary) / 0.9); +} + +.\[\&\:\:-webkit-slider-thumb\]\:h-4::-webkit-slider-thumb { + height: 1rem; +} + +.\[\&\:\:-webkit-slider-thumb\]\:w-4::-webkit-slider-thumb { + width: 1rem; +} + +.\[\&\:\:-webkit-slider-thumb\]\:cursor-pointer::-webkit-slider-thumb { + cursor: pointer; +} + +.\[\&\:\:-webkit-slider-thumb\]\:appearance-none::-webkit-slider-thumb { + -webkit-appearance: none; + appearance: none; +} + +.\[\&\:\:-webkit-slider-thumb\]\:rounded-full::-webkit-slider-thumb { + border-radius: 9999px; +} + +.\[\&\:\:-webkit-slider-thumb\]\:bg-primary::-webkit-slider-thumb { + --tw-bg-opacity: 1; + background-color: hsl(var(--primary) / var(--tw-bg-opacity)); +} + +.\[\&\:\:-webkit-slider-thumb\]\:transition-colors::-webkit-slider-thumb { + -webkit-transition-property: color, background-color, border-color, text-decoration-color, fill, stroke; + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; +} + +.\[\&\:\:-webkit-slider-thumb\]\:hover\:bg-primary\/90:hover::-webkit-slider-thumb { + background-color: hsl(var(--primary) / 0.9); +} + .\[\&\:has\(\:disabled\)\]\:cursor-not-allowed:has(:disabled) { cursor: not-allowed; } From 4d7bc1ba6af8a85c18c0745ebd27c2adb88d7cf5 Mon Sep 17 00:00:00 2001 From: axzilla Date: Fri, 22 Nov 2024 13:56:44 +0700 Subject: [PATCH 13/17] feat: add slider component --- assets/css/output.css | 27 ------ internals/ui/showcase/slider.templ | 30 ++++--- pkg/components/slider.templ | 53 +++++++----- pkg/components/slider_templ.go | 133 ++++++++++++++++++----------- pkg/styles/goilerplate.css | 27 ------ 5 files changed, 135 insertions(+), 135 deletions(-) diff --git a/assets/css/output.css b/assets/css/output.css index e0116b5..6beb739 100644 --- a/assets/css/output.css +++ b/assets/css/output.css @@ -1480,11 +1480,6 @@ body { background-color: rgb(255 255 255 / var(--tw-bg-opacity)); } -.bg-gray-200 { - --tw-bg-opacity: 1; - background-color: rgb(229 231 235 / var(--tw-bg-opacity)); -} - .bg-opacity-50 { --tw-bg-opacity: 0.5; } @@ -2509,10 +2504,6 @@ body { width: 1rem; } -.\[\&\:\:-moz-range-thumb\]\:cursor-pointer::-moz-range-thumb { - cursor: pointer; -} - .\[\&\:\:-moz-range-thumb\]\:rounded-full::-moz-range-thumb { border-radius: 9999px; } @@ -2526,13 +2517,6 @@ body { background-color: hsl(var(--primary) / var(--tw-bg-opacity)); } -.\[\&\:\:-moz-range-thumb\]\:transition-colors::-moz-range-thumb { - -moz-transition-property: color, background-color, border-color, text-decoration-color, fill, stroke; - transition-property: color, background-color, border-color, text-decoration-color, fill, stroke; - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); - transition-duration: 150ms; -} - .\[\&\:\:-moz-range-thumb\]\:hover\:bg-primary\/90:hover::-moz-range-thumb { background-color: hsl(var(--primary) / 0.9); } @@ -2545,10 +2529,6 @@ body { width: 1rem; } -.\[\&\:\:-webkit-slider-thumb\]\:cursor-pointer::-webkit-slider-thumb { - cursor: pointer; -} - .\[\&\:\:-webkit-slider-thumb\]\:appearance-none::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; @@ -2563,13 +2543,6 @@ body { background-color: hsl(var(--primary) / var(--tw-bg-opacity)); } -.\[\&\:\:-webkit-slider-thumb\]\:transition-colors::-webkit-slider-thumb { - -webkit-transition-property: color, background-color, border-color, text-decoration-color, fill, stroke; - transition-property: color, background-color, border-color, text-decoration-color, fill, stroke; - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); - transition-duration: 150ms; -} - .\[\&\:\:-webkit-slider-thumb\]\:hover\:bg-primary\/90:hover::-webkit-slider-thumb { background-color: hsl(var(--primary) / 0.9); } diff --git a/internals/ui/showcase/slider.templ b/internals/ui/showcase/slider.templ index 01b731f..a006d19 100644 --- a/internals/ui/showcase/slider.templ +++ b/internals/ui/showcase/slider.templ @@ -10,15 +10,14 @@ templ SliderShowcase() {

Default Slider

@components.Slider(components.SliderProps{ - ID: "default", - Name: "default", - Label: "Volume", - Value: 50, - Min: 0, - Max: 100, - Step: 1, - ShowValue: true, - Attributes: templ.Attributes{"x-ref": "text"}, + ID: "default", + Name: "default", + Label: "Volume", + Value: 50, + Min: 0, + Max: 100, + Step: 1, + ShowValue: true, })
@@ -32,7 +31,7 @@ templ SliderShowcase() { Max: 100, Step: 1, ShowValue: true, - ValueFormat: "%d%", + ValueFormat: "%", })
@@ -46,7 +45,7 @@ templ SliderShowcase() { Max: 40, Step: 1, ShowValue: true, - ValueFormat: "%d°C", + ValueFormat: "°C", })
@@ -60,7 +59,7 @@ templ SliderShowcase() { Max: 200, Step: 25, ShowValue: true, - ValueFormat: "%d%", + ValueFormat: "%", })
@@ -69,9 +68,12 @@ templ SliderShowcase() { ID: "disabled", Name: "disabled", Label: "Disabled Slider", - Value: 30, - ShowValue: true, + Value: 20, + Min: -20, + Max: 200, + Step: 20, Disabled: true, + ShowValue: true, })
diff --git a/pkg/components/slider.templ b/pkg/components/slider.templ index a0be316..6b56a42 100644 --- a/pkg/components/slider.templ +++ b/pkg/components/slider.templ @@ -1,5 +1,3 @@ -// pkg/components/slider.templ - package components import ( @@ -14,46 +12,57 @@ type SliderProps struct { // Name is the name attribute for the slider Name string - // Min is the minimum value of the slider + // Min sets the minimum value (default: 0) Min int - // Max is the maximum value of the slider + // Max sets the maximum value (default: 100) Max int - // Step is the increment between values + // Step defines the increment between values (default: 1) Step int - // Value is the initial value of the slider + // Value sets the initial value Value int // Label displays a label above the slider Label string - // ShowValue determines if the current value should be displayed + // ShowValue toggles the value display ShowValue bool - // ValueFormat is an optional format string for the displayed value (e.g. "%d°C") + // ValueFormat adds a suffix to the value (e.g. "%", "°C") ValueFormat string - // Class allows adding custom CSS classes + // Class adds custom CSS classes Class string - // Disabled determines if the slider is interactive + // Disabled makes the slider non-interactive Disabled bool - // Attributes allows passing additional HTML attributes + // Attributes for additional HTML attributes and Alpine.js bindings Attributes templ.Attributes } +// Slider renders a range input component with support for labels, value display and external binding. +// For detailed examples and usage guides, visit https://goilerplate.com/docs/components/slider +// +// Props: +// - ID: Unique identifier for the slider +// - Name: Input name attribute +// - Min: Minimum value (default: 0) +// - Max: Maximum value (default: 100) +// - Step: Value increment (default: 1) +// - Value: Initial value +// - Label: Optional label text +// - ShowValue: Show current value +// - ValueFormat: Optional format suffix (e.g. "%", "°C") +// - Class: Additional CSS classes +// - Disabled: Disables the slider +// - Attributes: Additional HTML attributes (e.g. x-model for binding) templ Slider(props SliderProps) {
if props.Label != "" || props.ShowValue {
@@ -63,18 +72,24 @@ templ Slider(props SliderProps) { } if props.ShowValue { - +

+ + if props.ValueFormat != "" { + { " " + props.ValueFormat } + } +

}
} ") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("

") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if props.ValueFormat != "" { + var templ_7745c5c3_Var5 string + templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(" " + props.ValueFormat) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/components/slider.templ`, Line: 78, Col: 32} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -144,7 +168,7 @@ func Slider(props SliderProps) templ.Component { return templ_7745c5c3_Err } } - var templ_7745c5c3_Var5 = []any{utils.TwMerge( + var templ_7745c5c3_Var6 = []any{utils.TwMerge( "w-full h-2 rounded-full bg-secondary appearance-none cursor-pointer", "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2", "[&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:w-4 [&::-webkit-slider-thumb]:h-4", @@ -156,20 +180,20 @@ func Slider(props SliderProps) templ.Component { "disabled:opacity-50 disabled:cursor-not-allowed", props.Class, )} - templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var5...) + templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var6...) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" Date: Fri, 22 Nov 2024 14:13:06 +0700 Subject: [PATCH 14/17] change: better ui on radiogroup component --- assets/css/output.css | 20 ++++++++++++++++++++ pkg/components/radio_group.templ | 7 ++++--- pkg/components/radio_group_templ.go | 15 ++++++++------- pkg/styles/goilerplate.css | 20 ++++++++++++++++++++ 4 files changed, 52 insertions(+), 10 deletions(-) diff --git a/assets/css/output.css b/assets/css/output.css index 6beb739..bbacf65 100644 --- a/assets/css/output.css +++ b/assets/css/output.css @@ -1993,11 +1993,31 @@ body { height: 0.5rem; } +.before\:h-1::before { + content: var(--tw-content); + height: 0.25rem; +} + +.before\:h-1\.5::before { + content: var(--tw-content); + height: 0.375rem; +} + .before\:w-2::before { content: var(--tw-content); width: 0.5rem; } +.before\:w-1::before { + content: var(--tw-content); + width: 0.25rem; +} + +.before\:w-1\.5::before { + content: var(--tw-content); + width: 0.375rem; +} + .before\:-translate-x-1\/2::before { content: var(--tw-content); --tw-translate-x: -50%; diff --git a/pkg/components/radio_group.templ b/pkg/components/radio_group.templ index d240be0..4718980 100644 --- a/pkg/components/radio_group.templ +++ b/pkg/components/radio_group.templ @@ -67,8 +67,9 @@ templ RadioGroupItem(props RadioGroupItemProps) {