From 4cf5175548d456a1f60079933b8c32a9b2e8866f Mon Sep 17 00:00:00 2001 From: anthdm Date: Sat, 22 Jun 2024 15:19:04 +0200 Subject: [PATCH] wip: ui components --- bootstrap/app/handlers/showcase.go | 11 + bootstrap/app/views/showcase/index.templ | 157 ++++++++++ bootstrap/public/assets/styles.css | 366 +++++++++++++++++++++++ go.sum | 20 ++ ui/button/button.go | 59 ++++ ui/card/card.templ | 29 ++ ui/card/card_templ.go | 175 +++++++++++ ui/input/input.go | 13 + ui/modal/modal.templ | 70 +++++ ui/modal/modal_templ.go | 159 ++++++++++ ui/table/table.templ | 54 ++++ ui/table/table_templ.go | 172 +++++++++++ ui/ui.go | 29 ++ 13 files changed, 1314 insertions(+) create mode 100644 bootstrap/app/handlers/showcase.go create mode 100644 bootstrap/app/views/showcase/index.templ create mode 100644 go.sum create mode 100644 ui/button/button.go create mode 100644 ui/card/card.templ create mode 100644 ui/card/card_templ.go create mode 100644 ui/input/input.go create mode 100644 ui/modal/modal.templ create mode 100644 ui/modal/modal_templ.go create mode 100644 ui/table/table.templ create mode 100644 ui/table/table_templ.go create mode 100644 ui/ui.go diff --git a/bootstrap/app/handlers/showcase.go b/bootstrap/app/handlers/showcase.go new file mode 100644 index 0000000..2153596 --- /dev/null +++ b/bootstrap/app/handlers/showcase.go @@ -0,0 +1,11 @@ +package handlers + +import ( + "AABBCCDD/app/views/showcase" + + "github.com/anthdm/superkit/kit" +) + +func HandleShowcaseIndex(kit *kit.Kit) error { + return kit.Render(showcase.Index()) +} diff --git a/bootstrap/app/views/showcase/index.templ b/bootstrap/app/views/showcase/index.templ new file mode 100644 index 0000000..904c6ca --- /dev/null +++ b/bootstrap/app/views/showcase/index.templ @@ -0,0 +1,157 @@ +package showcase + +import ( + "AABBCCDD/app/views/layouts" + "AABBCCDD/ui/button" + "AABBCCDD/ui/input" + "AABBCCDD/ui/modal" + "AABBCCDD/ui/card" + "AABBCCDD/ui" + "AABBCCDD/ui/table" +) + +templ Index() { + @layouts.App() { +
+
+

Buttons

+
+
+ + + + +
+
+
+

Forms

+
+
+
+ + +
+
+ + +
+
+ + +
+ +
+
+
+

Card

+
+ @card.Card(ui.Class("max-w-md")) { + @card.Header() { +

User registration

+

Please register to get the latest updates

+ } + @card.Content() { +
+
+ + +
+
+ + +
+
+ } + @card.Footer() { + + } + } +
+
+

Table

+
+
+ @table.Table() { + @table.Header(ui.Class("text-left")) { + +
+ +
+ + id + email + first name + last name + action + } + @table.Body() { + + +
+ +
+ + 1 + foo@foo.com + Anthony + GG + view + + + +
+ +
+ + 1 + foo@foo.com + Anthony + GG + view + + + +
+ +
+ + 1 + foo@foo.com + Anthony + GG + view + + + +
+ +
+ + 1 + foo@foo.com + Anthony + GG + view + + } + } +
+
+
+

Modal

+
+ @modal.Modal() { + @modal.Header() { + the header + } + @modal.Content() { + the content + } + @modal.Trigger() { +
trigger me
+ } + } +
+
+ } +} diff --git a/bootstrap/public/assets/styles.css b/bootstrap/public/assets/styles.css index 3824ab2..97f2d7f 100644 --- a/bootstrap/public/assets/styles.css +++ b/bootstrap/public/assets/styles.css @@ -629,23 +629,63 @@ body { position: fixed; } +.absolute { + position: absolute; +} + +.relative { + position: relative; +} + +.inset-0 { + inset: 0px; +} + +.left-0 { + left: 0px; +} + +.right-0 { + right: 0px; +} + .right-6 { right: 1.5rem; } +.top-0 { + top: 0px; +} + .top-6 { top: 1.5rem; } +.z-50 { + z-index: 50; +} + +.z-\[99\] { + z-index: 99; +} + .mx-auto { margin-left: auto; margin-right: auto; } +.mb-6 { + margin-bottom: 1.5rem; +} + .ml-4 { margin-left: 1rem; } +.mr-5 { + margin-right: 1.25rem; +} + .mt-10 { margin-top: 2.5rem; } @@ -654,6 +694,14 @@ body { margin-top: 8rem; } +.mt-5 { + margin-top: 1.25rem; +} + +.mt-8 { + margin-top: 2rem; +} + .inline-block { display: inline-block; } @@ -666,14 +714,58 @@ body { display: inline-flex; } +.table { + display: table; +} + .hidden { display: none; } +.h-10 { + height: 2.5rem; +} + +.h-4 { + height: 1rem; +} + +.h-5 { + height: 1.25rem; +} + +.h-8 { + height: 2rem; +} + +.h-auto { + height: auto; +} + +.h-full { + height: 100%; +} + .h-screen { height: 100vh; } +.w-4 { + width: 1rem; +} + +.w-5 { + width: 1.25rem; +} + +.w-8 { + width: 2rem; +} + +.w-auto { + width: auto; +} + .w-fit { width: -moz-fit-content; width: fit-content; @@ -683,10 +775,22 @@ body { width: 100%; } +.w-screen { + width: 100vw; +} + +.min-w-full { + min-width: 100%; +} + .max-w-2xl { max-width: 42rem; } +.max-w-4xl { + max-width: 56rem; +} + .max-w-7xl { max-width: 80rem; } @@ -699,6 +803,20 @@ body { max-width: 24rem; } +.max-w-xs { + max-width: 20rem; +} + +.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-4 { + --tw-translate-y: 1rem; + 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-pointer { cursor: pointer; } @@ -755,6 +873,36 @@ body { gap: 2rem; } +.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)); +} + +.overflow-hidden { + overflow: hidden; +} + +.overflow-x-auto { + overflow-x: auto; +} + +.whitespace-nowrap { + white-space: nowrap; +} + +.rounded { + border-radius: 0.25rem; +} + +.rounded-full { + border-radius: 9999px; +} + +.rounded-lg { + border-radius: var(--radius); +} + .rounded-md { border-radius: calc(var(--radius) - 2px); } @@ -772,20 +920,49 @@ body { 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-red-500 { --tw-border-opacity: 1; border-color: rgb(239 68 68 / var(--tw-border-opacity)); } +.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-primary { --tw-bg-opacity: 1; background-color: hsl(var(--primary) / var(--tw-bg-opacity)); } +.bg-secondary { + --tw-bg-opacity: 1; + background-color: hsl(var(--secondary) / var(--tw-bg-opacity)); +} + .bg-transparent { background-color: transparent; } +.bg-opacity-40 { + --tw-bg-opacity: 0.4; +} + .bg-gradient-to-r { background-image: linear-gradient(to right, var(--tw-gradient-stops)); } @@ -810,6 +987,10 @@ body { background-clip: text; } +.p-6 { + padding: 1.5rem; +} + .px-3 { padding-left: 0.75rem; padding-right: 0.75rem; @@ -820,16 +1001,31 @@ body { padding-right: 1rem; } +.px-5 { + padding-left: 1.25rem; + padding-right: 1.25rem; +} + .px-6 { padding-left: 1.5rem; padding-right: 1.5rem; } +.px-7 { + padding-left: 1.75rem; + padding-right: 1.75rem; +} + .px-8 { padding-left: 2rem; padding-right: 2rem; } +.py-1 { + padding-top: 0.25rem; + padding-bottom: 0.25rem; +} + .py-12 { padding-top: 3rem; padding-bottom: 3rem; @@ -845,10 +1041,45 @@ body { padding-bottom: 0.75rem; } +.py-4 { + padding-top: 1rem; + padding-bottom: 1rem; +} + +.py-6 { + padding-top: 1.5rem; + padding-bottom: 1.5rem; +} + +.py-8 { + padding-top: 2rem; + padding-bottom: 2rem; +} + +.pb-2 { + padding-bottom: 0.5rem; +} + +.pt-0 { + padding-top: 0px; +} + +.pt-2 { + padding-top: 0.5rem; +} + +.text-left { + text-align: left; +} + .text-center { text-align: center; } +.text-right { + text-align: right; +} + .align-middle { vertical-align: middle; } @@ -908,16 +1139,35 @@ body { letter-spacing: 0.025em; } +.text-blue-500 { + --tw-text-opacity: 1; + color: rgb(59 130 246 / var(--tw-text-opacity)); +} + +.text-card-foreground { + --tw-text-opacity: 1; + color: hsl(var(--card-foreground) / var(--tw-text-opacity)); +} + .text-foreground { --tw-text-opacity: 1; color: hsl(var(--foreground) / var(--tw-text-opacity)); } +.text-foreground\/60 { + color: hsl(var(--foreground) / 0.6); +} + .text-muted-foreground { --tw-text-opacity: 1; color: hsl(var(--muted-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)); @@ -932,16 +1182,33 @@ body { color: transparent; } +.text-white { + --tw-text-opacity: 1; + color: rgb(255 255 255 / var(--tw-text-opacity)); +} + .underline { text-decoration-line: underline; } +.opacity-0 { + opacity: 0; +} + +.opacity-100 { + opacity: 1; +} + .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); } +.outline { + outline-style: solid; +} + .ring-offset-background { --tw-ring-offset-color: hsl(var(--background) / 1); } @@ -956,12 +1223,51 @@ body { transition-duration: 200ms; } +.duration-300 { + transition-duration: 300ms; +} + +.ease-in { + transition-timing-function: cubic-bezier(0.4, 0, 1, 1); +} + +.ease-out { + transition-timing-function: cubic-bezier(0, 0, 0.2, 1); +} + /* fix for Alpine users. */ [x-cloak] { display: none !important; } +.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; +} + +.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)); +} + .placeholder\:text-neutral-500::-moz-placeholder { --tw-text-opacity: 1; color: rgb(115 115 115 / var(--tw-text-opacity)); @@ -972,10 +1278,27 @@ body { color: rgb(115 115 115 / var(--tw-text-opacity)); } +.hover\:bg-destructive\/80:hover { + background-color: hsl(var(--destructive) / 0.8); +} + .hover\:bg-primary\/90:hover { background-color: hsl(var(--primary) / 0.9); } +.hover\:bg-secondary:hover { + --tw-bg-opacity: 1; + background-color: hsl(var(--secondary) / var(--tw-bg-opacity)); +} + +.hover\:bg-secondary\/80:hover { + background-color: hsl(var(--secondary) / 0.8); +} + +.hover\:text-foreground\/80:hover { + color: hsl(var(--foreground) / 0.8); +} + .focus\:border-neutral-300:focus { --tw-border-opacity: 1; border-color: rgb(212 212 212 / var(--tw-border-opacity)); @@ -997,6 +1320,22 @@ body { --tw-ring-color: hsl(var(--primary) / var(--tw-ring-opacity)); } +.focus-visible\:outline-none:focus-visible { + outline: 2px solid transparent; + outline-offset: 2px; +} + +.focus-visible\:ring-1: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(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); +} + +.focus-visible\:ring-ring:focus-visible { + --tw-ring-opacity: 1; + --tw-ring-color: hsl(var(--ring) / var(--tw-ring-opacity)); +} + .disabled\:cursor-not-allowed:disabled { cursor: not-allowed; } @@ -1005,6 +1344,33 @@ body { opacity: 0.5; } +@media (min-width: 640px) { + .sm\:max-w-lg { + max-width: 32rem; + } + + .sm\: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)); + } + + .sm\: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)); + } + + .sm\: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)); + } + + .sm\:rounded-lg { + border-radius: var(--radius); + } +} + @media (min-width: 1024px) { .lg\:mt-20 { margin-top: 5rem; diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..1f527fe --- /dev/null +++ b/go.sum @@ -0,0 +1,20 @@ +github.com/a-h/templ v0.2.707 h1:T1Gkd2ugbRglZ9rYw/VBchWOSZVKmetDbBkm4YubM7U= +github.com/a-h/templ v0.2.707/go.mod h1:5cqsugkq9IerRNucNsI4DEamdHPsoGMQy99DzydLhM8= +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/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA= +github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo= +github.com/gorilla/sessions v1.3.0 h1:XYlkq7KcpOB2ZhHBPv5WpjMIxrQosiZanfoy1HLZFzg= +github.com/gorilla/sessions v1.3.0/go.mod h1:ePLdVu+jbEgHH+KWw8I1z2wqd0BAdAQh/8LRvBeoNcQ= +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/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/ui/button/button.go b/ui/button/button.go new file mode 100644 index 0000000..3820e6b --- /dev/null +++ b/ui/button/button.go @@ -0,0 +1,59 @@ +package button + +import ( + "AABBCCDD/ui" + + "github.com/a-h/templ" +) + +const ( + buttonBaseClass = "inline-flex items-center justify-center px-4 py-2 font-medium text-sm tracking-wide transition-colors duration-200 rounded-md focus:ring focus:shadow-outline focus:outline-none" + buttonVariantPrimary = "text-primary-foreground bg-primary focus:ring-primary hover:bg-primary/90" + buttonVariantOutline = "text-primary border border-primary hover:bg-secondary focus:ring-primary" + buttonVariantSecondary = "text-primary bg-secondary hover:bg-secondary/80" + buttonVariantDestructive = "text-primary bg-destructive hover:bg-destructive/80" +) + +func New(opts ...func(*templ.Attributes)) templ.Attributes { + return ui.CreateAttrs(buttonBaseClass, buttonVariantPrimary, opts...) +} + +func Outline(opts ...func(*templ.Attributes)) templ.Attributes { + return appendVariant("outline", opts...) +} + +func Primary(opts ...func(*templ.Attributes)) templ.Attributes { + return appendVariant("primary", opts...) +} + +func Secondary(opts ...func(*templ.Attributes)) templ.Attributes { + return appendVariant("secondary", opts...) +} + +func Destructive(opts ...func(*templ.Attributes)) templ.Attributes { + return appendVariant("destructive", opts...) +} + +func Variant(variant string) func(*templ.Attributes) { + return func(attrs *templ.Attributes) { + att := *attrs + switch variant { + case "primary": + att["class"] = ui.Merge(buttonBaseClass, buttonVariantPrimary) + case "outline": + att["class"] = ui.Merge(buttonBaseClass, buttonVariantOutline) + case "secondary": + att["class"] = ui.Merge(buttonBaseClass, buttonVariantSecondary) + case "destructive": + att["class"] = ui.Merge(buttonBaseClass, buttonVariantDestructive) + } + } +} + +func appendVariant(variant string, opts ...func(*templ.Attributes)) templ.Attributes { + opt := []func(*templ.Attributes){ + Variant(variant), + } + opt = append(opt, opts...) + return New(opt...) +} diff --git a/ui/card/card.templ b/ui/card/card.templ new file mode 100644 index 0000000..6ca2beb --- /dev/null +++ b/ui/card/card.templ @@ -0,0 +1,29 @@ +package card + +import "AABBCCDD/ui" + +const cardBaseClass = "rounded-lg border bg-card text-card-foreground shadow-sm" + +templ Card(opts ...func(*templ.Attributes)) { +
+ { children... } +
+} + +templ Header(opts ...func(*templ.Attributes)) { +
+ { children... } +
+} + +templ Content(opts ...func(*templ.Attributes)) { +
+ { children... } +
+} + +templ Footer(opts ...func(*templ.Attributes)) { +
+ { children... } +
+} diff --git a/ui/card/card_templ.go b/ui/card/card_templ.go new file mode 100644 index 0000000..2e85b03 --- /dev/null +++ b/ui/card/card_templ.go @@ -0,0 +1,175 @@ +// Code generated by templ - DO NOT EDIT. + +// templ: version: v0.2.707 +package card + +//lint:file-ignore SA4006 This context is only used if a nested component is present. + +import "github.com/a-h/templ" +import "context" +import "io" +import "bytes" + +import "AABBCCDD/ui" + +const cardBaseClass = "rounded-lg border bg-card text-card-foreground shadow-sm" + +func Card(opts ...func(*templ.Attributes)) templ.Component { + return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) { + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer) + if !templ_7745c5c3_IsBuffer { + templ_7745c5c3_Buffer = templ.GetBuffer() + defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) + } + 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 + } + templ_7745c5c3_Err = templ_7745c5c3_Var1.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 !templ_7745c5c3_IsBuffer { + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W) + } + return templ_7745c5c3_Err + }) +} + +func Header(opts ...func(*templ.Attributes)) templ.Component { + return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) { + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer) + if !templ_7745c5c3_IsBuffer { + templ_7745c5c3_Buffer = templ.GetBuffer() + defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var2 := templ.GetChildren(ctx) + if templ_7745c5c3_Var2 == nil { + templ_7745c5c3_Var2 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ_7745c5c3_Var2.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 !templ_7745c5c3_IsBuffer { + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W) + } + return templ_7745c5c3_Err + }) +} + +func Content(opts ...func(*templ.Attributes)) templ.Component { + return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) { + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer) + if !templ_7745c5c3_IsBuffer { + templ_7745c5c3_Buffer = templ.GetBuffer() + defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var3 := templ.GetChildren(ctx) + if templ_7745c5c3_Var3 == nil { + templ_7745c5c3_Var3 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ_7745c5c3_Var3.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 !templ_7745c5c3_IsBuffer { + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W) + } + return templ_7745c5c3_Err + }) +} + +func Footer(opts ...func(*templ.Attributes)) templ.Component { + return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) { + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer) + if !templ_7745c5c3_IsBuffer { + templ_7745c5c3_Buffer = templ.GetBuffer() + defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var4 := templ.GetChildren(ctx) + if templ_7745c5c3_Var4 == nil { + templ_7745c5c3_Var4 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ_7745c5c3_Var4.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 !templ_7745c5c3_IsBuffer { + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W) + } + return templ_7745c5c3_Err + }) +} diff --git a/ui/input/input.go b/ui/input/input.go new file mode 100644 index 0000000..b6ed87d --- /dev/null +++ b/ui/input/input.go @@ -0,0 +1,13 @@ +package input + +import ( + "github.com/a-h/templ" + + "AABBCCDD/ui" +) + +const defaultInputClass = "flex h-10 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50" + +func Input(opts ...func(*templ.Attributes)) templ.Attributes { + return ui.CreateAttrs(defaultInputClass, "", opts...) +} diff --git a/ui/modal/modal.templ b/ui/modal/modal.templ new file mode 100644 index 0000000..895aad1 --- /dev/null +++ b/ui/modal/modal.templ @@ -0,0 +1,70 @@ +package modal + +templ Modal() { +
+
+ foo +
+ +
+} + +templ Header() { +
+

+ { children... } +

+ +
+} + +templ Content() { +
+ { children... } +
+} + +templ Trigger() { +
+ { children... } +
+} + +templ Footer() { +} diff --git a/ui/modal/modal_templ.go b/ui/modal/modal_templ.go new file mode 100644 index 0000000..b4b69bd --- /dev/null +++ b/ui/modal/modal_templ.go @@ -0,0 +1,159 @@ +// Code generated by templ - DO NOT EDIT. + +// templ: version: v0.2.707 +package modal + +//lint:file-ignore SA4006 This context is only used if a nested component is present. + +import "github.com/a-h/templ" +import "context" +import "io" +import "bytes" + +func Modal() templ.Component { + return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) { + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer) + if !templ_7745c5c3_IsBuffer { + templ_7745c5c3_Buffer = templ.GetBuffer() + defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) + } + 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("
foo
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if !templ_7745c5c3_IsBuffer { + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W) + } + return templ_7745c5c3_Err + }) +} + +func Header() templ.Component { + return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) { + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer) + if !templ_7745c5c3_IsBuffer { + templ_7745c5c3_Buffer = templ.GetBuffer() + defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var2 := templ.GetChildren(ctx) + if templ_7745c5c3_Var2 == nil { + templ_7745c5c3_Var2 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("

") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ_7745c5c3_Var2.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 !templ_7745c5c3_IsBuffer { + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W) + } + return templ_7745c5c3_Err + }) +} + +func Content() templ.Component { + return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) { + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer) + if !templ_7745c5c3_IsBuffer { + templ_7745c5c3_Buffer = templ.GetBuffer() + defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var3 := templ.GetChildren(ctx) + if templ_7745c5c3_Var3 == nil { + templ_7745c5c3_Var3 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ_7745c5c3_Var3.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 !templ_7745c5c3_IsBuffer { + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W) + } + return templ_7745c5c3_Err + }) +} + +func Trigger() templ.Component { + return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) { + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer) + if !templ_7745c5c3_IsBuffer { + templ_7745c5c3_Buffer = templ.GetBuffer() + defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var4 := templ.GetChildren(ctx) + if templ_7745c5c3_Var4 == nil { + templ_7745c5c3_Var4 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ_7745c5c3_Var4.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 !templ_7745c5c3_IsBuffer { + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W) + } + return templ_7745c5c3_Err + }) +} + +func Footer() templ.Component { + return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) { + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer) + if !templ_7745c5c3_IsBuffer { + templ_7745c5c3_Buffer = templ.GetBuffer() + defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var5 := templ.GetChildren(ctx) + if templ_7745c5c3_Var5 == nil { + templ_7745c5c3_Var5 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + if !templ_7745c5c3_IsBuffer { + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W) + } + return templ_7745c5c3_Err + }) +} diff --git a/ui/table/table.templ b/ui/table/table.templ new file mode 100644 index 0000000..c7089c7 --- /dev/null +++ b/ui/table/table.templ @@ -0,0 +1,54 @@ +package table + +import ( + "AABBCCDD/ui" +) + +templ Table() { +
+
+
+
+ + { children... } +
+
+
+
+
+} + +templ Header(opts ...func(*templ.Attributes)) { + + + { children... } + + +} + +templ Body(opts ...func(*templ.Attributes)) { + + { children... } + +} + +templ Footer(opts ...func(*templ.Attributes)) { + + + { children... } + + +} + +const ( + thBaseClass = "px-5 py-3 text-xs font-medium uppercase" + tdBaseClass = "px-5 py-4 text-sm whitespace-nowrap" +) + +func Td(opts ...func(*templ.Attributes)) templ.Attributes { + return ui.CreateAttrs(tdBaseClass, "", opts...) +} + +func Th(opts ...func(*templ.Attributes)) templ.Attributes { + return ui.CreateAttrs(thBaseClass, "", opts...) +} diff --git a/ui/table/table_templ.go b/ui/table/table_templ.go new file mode 100644 index 0000000..33cbb30 --- /dev/null +++ b/ui/table/table_templ.go @@ -0,0 +1,172 @@ +// Code generated by templ - DO NOT EDIT. + +// templ: version: v0.2.707 +package table + +//lint:file-ignore SA4006 This context is only used if a nested component is present. + +import "github.com/a-h/templ" +import "context" +import "io" +import "bytes" + +import ( + "AABBCCDD/ui" +) + +func Table() templ.Component { + return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) { + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer) + if !templ_7745c5c3_IsBuffer { + templ_7745c5c3_Buffer = templ.GetBuffer() + defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) + } + 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 + } + templ_7745c5c3_Err = templ_7745c5c3_Var1.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 !templ_7745c5c3_IsBuffer { + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W) + } + return templ_7745c5c3_Err + }) +} + +func Header(opts ...func(*templ.Attributes)) templ.Component { + return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) { + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer) + if !templ_7745c5c3_IsBuffer { + templ_7745c5c3_Buffer = templ.GetBuffer() + defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var2 := templ.GetChildren(ctx) + if templ_7745c5c3_Var2 == nil { + templ_7745c5c3_Var2 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ_7745c5c3_Var2.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 !templ_7745c5c3_IsBuffer { + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W) + } + return templ_7745c5c3_Err + }) +} + +func Body(opts ...func(*templ.Attributes)) templ.Component { + return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) { + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer) + if !templ_7745c5c3_IsBuffer { + templ_7745c5c3_Buffer = templ.GetBuffer() + defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var3 := templ.GetChildren(ctx) + if templ_7745c5c3_Var3 == nil { + templ_7745c5c3_Var3 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ_7745c5c3_Var3.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 !templ_7745c5c3_IsBuffer { + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W) + } + return templ_7745c5c3_Err + }) +} + +func Footer(opts ...func(*templ.Attributes)) templ.Component { + return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) { + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer) + if !templ_7745c5c3_IsBuffer { + templ_7745c5c3_Buffer = templ.GetBuffer() + defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var4 := templ.GetChildren(ctx) + if templ_7745c5c3_Var4 == nil { + templ_7745c5c3_Var4 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ_7745c5c3_Var4.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 !templ_7745c5c3_IsBuffer { + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W) + } + return templ_7745c5c3_Err + }) +} + +const ( + thBaseClass = "px-5 py-3 text-xs font-medium uppercase" + tdBaseClass = "px-5 py-4 text-sm whitespace-nowrap" +) + +func Td(opts ...func(*templ.Attributes)) templ.Attributes { + return ui.CreateAttrs(tdBaseClass, "", opts...) +} + +func Th(opts ...func(*templ.Attributes)) templ.Attributes { + return ui.CreateAttrs(thBaseClass, "", opts...) +} diff --git a/ui/ui.go b/ui/ui.go new file mode 100644 index 0000000..7460d0d --- /dev/null +++ b/ui/ui.go @@ -0,0 +1,29 @@ +package ui + +import ( + "fmt" + + "github.com/a-h/templ" +) + +func CreateAttrs(baseClass string, defaultClass string, opts ...func(*templ.Attributes)) templ.Attributes { + attrs := templ.Attributes{ + "class": baseClass + " " + defaultClass, + } + for _, o := range opts { + o(&attrs) + } + return attrs +} + +func Merge(a, b string) string { + return fmt.Sprintf("%s %s", a, b) +} + +func Class(class string) func(*templ.Attributes) { + return func(attrs *templ.Attributes) { + attr := *attrs + class := attr["class"].(string) + " " + class + attr["class"] = class + } +}