Compare commits

...

1 commit

Author SHA1 Message Date
anthdm
4cf5175548 wip: ui components 2024-06-22 15:19:04 +02:00
13 changed files with 1314 additions and 0 deletions

View file

@ -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())
}

View file

@ -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() {
<div class="flex flex-col gap-10 mt-10 py-8">
<div>
<h1 class="text-2xl font-semibold">Buttons</h1>
<div class="border-b pt-2 mb-6"></div>
<div class="flex gap-4">
<button { button.Primary()... }>primary</button>
<button { button.Outline()... }>outline</button>
<button { button.Secondary()... }>secondary</button>
<button { button.Destructive()... }>destructive</button>
</div>
</div>
<div>
<h1 class="text-2xl font-semibold">Forms</h1>
<div class="border-b pt-2 mb-6"></div>
<form class="flex flex-col gap-4 w-full max-w-xs">
<div class="flex flex-col gap-2">
<label class="text-sm">Email</label>
<input name="email" type="email" placeholder="enter your email" { input.Input()... }/>
</div>
<div class="flex flex-col gap-2">
<label class="text-sm">First Name</label>
<input name="firstName" type="text" placeholder="first name" { input.Input()... }/>
</div>
<div class="flex flex-col gap-2">
<label class="text-sm">Last Name</label>
<input name="lastName" type="text" placeholder="last name" { input.Input()... }/>
</div>
<button type="button" { button.Primary(ui.Class("w-fit"))... }>submit</button>
</form>
</div>
<div>
<h1 class="text-2xl font-semibold">Card</h1>
<div class="border-b pt-2 mb-6"></div>
@card.Card(ui.Class("max-w-md")) {
@card.Header() {
<h1 class="text-xl">User registration</h1>
<h2 class="text-muted-foreground">Please register to get the latest updates</h2>
}
@card.Content() {
<form class="flex flex-col gap-4">
<div class="flex flex-col gap-1">
<label class="text-sm">Username</label>
<input { input.Input()... }/>
</div>
<div class="flex flex-col gap-1">
<label class="text-sm">Email</label>
<input { input.Input()... }/>
</div>
</form>
}
@card.Footer() {
<button { button.Primary()... }>Submit</button>
}
}
</div>
<div>
<h1 class="text-2xl font-semibold">Table</h1>
<div class="border-b pt-2 mb-6"></div>
<div class="max-w-4xl">
@table.Table() {
@table.Header(ui.Class("text-left")) {
<th { table.Th()... }>
<div class="flex items-center">
<input id="checkbox-id" type="checkbox" class="w-4 h-4 bg-transparent border-input rounded"/>
</div>
</th>
<th { table.Th()... }>id</th>
<th { table.Th()... }>email</th>
<th { table.Th()... }>first name</th>
<th { table.Th()... }>last name</th>
<th { table.Th(ui.Class("text-right"))... }>action</th>
}
@table.Body() {
<tr>
<td { table.Td()... }>
<div class="flex items-center">
<input id="checkbox-id" type="checkbox" class="w-4 h-4 bg-transparent border-input rounded"/>
</div>
</td>
<td { table.Td()... }>1</td>
<td { table.Td()... }>foo@foo.com</td>
<td { table.Td()... }>Anthony</td>
<td { table.Td()... }>GG</td>
<td { table.Td(ui.Class("text-right text-blue-500"))... }>view</td>
</tr>
<tr>
<td { table.Td()... }>
<div class="flex items-center">
<input id="checkbox-id" type="checkbox" class="w-4 h-4 bg-transparent border-input rounded"/>
</div>
</td>
<td { table.Td()... }>1</td>
<td { table.Td()... }>foo@foo.com</td>
<td { table.Td()... }>Anthony</td>
<td { table.Td()... }>GG</td>
<td { table.Td(ui.Class("text-right text-blue-500"))... }>view</td>
</tr>
<tr>
<td { table.Td()... }>
<div class="flex items-center">
<input id="checkbox-id" type="checkbox" class="w-4 h-4 bg-transparent border-input rounded"/>
</div>
</td>
<td { table.Td()... }>1</td>
<td { table.Td()... }>foo@foo.com</td>
<td { table.Td()... }>Anthony</td>
<td { table.Td()... }>GG</td>
<td { table.Td(ui.Class("text-right text-blue-500"))... }>view</td>
</tr>
<tr>
<td { table.Td()... }>
<div class="flex items-center">
<input id="checkbox-id" type="checkbox" class="w-4 h-4 bg-transparent border-input rounded"/>
</div>
</td>
<td { table.Td()... }>1</td>
<td { table.Td()... }>foo@foo.com</td>
<td { table.Td()... }>Anthony</td>
<td { table.Td()... }>GG</td>
<td { table.Td(ui.Class("text-right text-blue-500"))... }>view</td>
</tr>
}
}
</div>
</div>
<div>
<h1 class="text-2xl font-semibold">Modal</h1>
<div class="border-b pt-2 mb-6"></div>
@modal.Modal() {
@modal.Header() {
the header
}
@modal.Content() {
the content
}
@modal.Trigger() {
<div class="text-white">trigger me</div>
}
}
</div>
</div>
}
}

View file

@ -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;

20
go.sum Normal file
View file

@ -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=

59
ui/button/button.go Normal file
View file

@ -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...)
}

29
ui/card/card.templ Normal file
View file

@ -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)) {
<div { ui.CreateAttrs(cardBaseClass, "", opts...)... }>
{ children... }
</div>
}
templ Header(opts ...func(*templ.Attributes)) {
<div { ui.CreateAttrs("p-6", "", opts...)... }>
{ children... }
</div>
}
templ Content(opts ...func(*templ.Attributes)) {
<div { ui.CreateAttrs("p-6 pt-0", "", opts...)... }>
{ children... }
</div>
}
templ Footer(opts ...func(*templ.Attributes)) {
<div { ui.CreateAttrs("p-6 pt-0", "", opts...)... }>
{ children... }
</div>
}

175
ui/card/card_templ.go Normal file
View file

@ -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("<div")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templ.RenderAttributes(ctx, templ_7745c5c3_Buffer, ui.CreateAttrs(cardBaseClass, "", opts...))
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
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>")
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("<div")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templ.RenderAttributes(ctx, templ_7745c5c3_Buffer, ui.CreateAttrs("p-6", "", opts...))
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_Var2.Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>")
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("<div")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templ.RenderAttributes(ctx, templ_7745c5c3_Buffer, ui.CreateAttrs("p-6 pt-0", "", opts...))
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_Var3.Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>")
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("<div")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templ.RenderAttributes(ctx, templ_7745c5c3_Buffer, ui.CreateAttrs("p-6 pt-0", "", opts...))
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_Var4.Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>")
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
})
}

13
ui/input/input.go Normal file
View file

@ -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...)
}

70
ui/modal/modal.templ Normal file
View file

@ -0,0 +1,70 @@
package modal
templ Modal() {
<div
x-data="{ modalOpen: false }"
@keydown.escape.window="modalOpen = false"
class="relative z-50 w-auto h-auto"
>
<div @click="modalOpen=true">
foo
</div>
<template x-teleport="body">
<div x-show="modalOpen" class="fixed top-0 left-0 z-[99] flex items-center justify-center w-screen h-screen" x-cloak>
<div
x-show="modalOpen"
x-transition:enter="ease-out duration-300"
x-transition:enter-start="opacity-0"
x-transition:enter-end="opacity-100"
x-transition:leave="ease-in duration-300"
x-transition:leave-start="opacity-100"
x-transition:leave-end="opacity-0"
@click="modalOpen=false"
class="absolute inset-0 w-full h-full bg-black bg-opacity-40"
></div>
<div
x-show="modalOpen"
x-trap.inert.noscroll="modalOpen"
x-transition:enter="ease-out duration-300"
x-transition:enter-start="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
x-transition:enter-end="opacity-100 translate-y-0 sm:scale-100"
x-transition:leave="ease-in duration-200"
x-transition:leave-start="opacity-100 translate-y-0 sm:scale-100"
x-transition:leave-end="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
class="relative w-full py-6 px-7 sm:max-w-lg sm:rounded-lg"
>
{ children... }
<div @click="modalOpen=true">
foo
</div>
</div>
</div>
</template>
</div>
}
templ Header() {
<div class="flex items-center justify-between pb-2">
<h3 class="text-lg font-semibold">
{ children... }
</h3>
<button @click="modalOpen=false" class="absolute top-0 right-0 flex items-center justify-center w-8 h-8 mt-5 mr-5 rounded-full">
<svg class="w-5 h-5" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"></path></svg>
</button>
</div>
}
templ Content() {
<div class="relative w-auto">
{ children... }
</div>
}
templ Trigger() {
<div @click="modalOpen=true">
{ children... }
</div>
}
templ Footer() {
}

159
ui/modal/modal_templ.go Normal file
View file

@ -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("<div x-data=\"{ modalOpen: false }\" @keydown.escape.window=\"modalOpen = false\" class=\"relative z-50 w-auto h-auto\"><div @click=\"modalOpen=true\">foo</div><template x-teleport=\"body\"><div x-show=\"modalOpen\" class=\"fixed top-0 left-0 z-[99] flex items-center justify-center w-screen h-screen\" x-cloak><div x-show=\"modalOpen\" x-transition:enter=\"ease-out duration-300\" x-transition:enter-start=\"opacity-0\" x-transition:enter-end=\"opacity-100\" x-transition:leave=\"ease-in duration-300\" x-transition:leave-start=\"opacity-100\" x-transition:leave-end=\"opacity-0\" @click=\"modalOpen=false\" class=\"absolute inset-0 w-full h-full bg-black bg-opacity-40\"></div><div x-show=\"modalOpen\" x-trap.inert.noscroll=\"modalOpen\" x-transition:enter=\"ease-out duration-300\" x-transition:enter-start=\"opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95\" x-transition:enter-end=\"opacity-100 translate-y-0 sm:scale-100\" x-transition:leave=\"ease-in duration-200\" x-transition:leave-start=\"opacity-100 translate-y-0 sm:scale-100\" x-transition:leave-end=\"opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95\" class=\"relative w-full py-6 px-7 sm:max-w-lg sm:rounded-lg\">")
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("<div @click=\"modalOpen=true\">foo</div></div></div></template></div>")
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("<div class=\"flex items-center justify-between pb-2\"><h3 class=\"text-lg font-semibold\">")
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("</h3><button @click=\"modalOpen=false\" class=\"absolute top-0 right-0 flex items-center justify-center w-8 h-8 mt-5 mr-5 rounded-full\"><svg class=\"w-5 h-5\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M6 18L18 6M6 6l12 12\"></path></svg></button></div>")
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("<div class=\"relative w-auto\">")
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("</div>")
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("<div @click=\"modalOpen=true\">")
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("</div>")
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
})
}

54
ui/table/table.templ Normal file
View file

@ -0,0 +1,54 @@
package table
import (
"AABBCCDD/ui"
)
templ Table() {
<div class="flex flex-col border rounded-md">
<div class="overflow-x-auto">
<div class="inline-block min-w-full">
<div class="overflow-hidden">
<table class="min-w-full divide-y">
{ children... }
</table>
</div>
</div>
</div>
</div>
}
templ Header(opts ...func(*templ.Attributes)) {
<thead { ui.CreateAttrs("", "", opts...)... }>
<tr>
{ children... }
</tr>
</thead>
}
templ Body(opts ...func(*templ.Attributes)) {
<tbody { ui.CreateAttrs("divide-y", "", opts...)... }>
{ children... }
</tbody>
}
templ Footer(opts ...func(*templ.Attributes)) {
<tfoot>
<tr>
{ children... }
</tr>
</tfoot>
}
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...)
}

172
ui/table/table_templ.go Normal file
View file

@ -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("<div class=\"flex flex-col border rounded-md\"><div class=\"overflow-x-auto\"><div class=\"inline-block min-w-full\"><div class=\"overflow-hidden\"><table class=\"min-w-full divide-y\">")
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("</table></div></div></div></div>")
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("<thead")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templ.RenderAttributes(ctx, templ_7745c5c3_Buffer, ui.CreateAttrs("", "", opts...))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("><tr>")
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("</tr></thead>")
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("<tbody")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templ.RenderAttributes(ctx, templ_7745c5c3_Buffer, ui.CreateAttrs("divide-y", "", opts...))
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_Var3.Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</tbody>")
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("<tfoot><tr>")
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("</tr></tfoot>")
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...)
}

29
ui/ui.go Normal file
View file

@ -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
}
}