1
0
mirror of https://github.com/axzilla/templui.git synced 2025-02-21 20:33:00 +00:00

feat: add input component wip

This commit is contained in:
“axzilla” 2024-10-07 08:32:02 +02:00
parent fa59e4f47b
commit 683e34fb62
6 changed files with 306 additions and 0 deletions

View File

@ -628,6 +628,10 @@ body {
}
}
.pointer-events-none {
pointer-events: none;
}
.static {
position: static;
}
@ -702,6 +706,14 @@ body {
z-index: 50;
}
.m-32 {
margin: 8rem;
}
.m-0 {
margin: 0px;
}
.mx-auto {
margin-left: auto;
margin-right: auto;
@ -767,6 +779,10 @@ body {
display: inline-flex;
}
.grid {
display: grid;
}
.hidden {
display: none;
}
@ -791,6 +807,10 @@ body {
height: 1rem;
}
.h-5 {
height: 1.25rem;
}
.h-6 {
height: 1.5rem;
}
@ -839,6 +859,10 @@ body {
width: 1rem;
}
.w-5 {
width: 1.25rem;
}
.w-6 {
width: 1.5rem;
}
@ -855,6 +879,10 @@ body {
width: 100%;
}
.w-1\/2 {
width: 50%;
}
.max-w-3xl {
max-width: 48rem;
}
@ -863,10 +891,22 @@ body {
max-width: 80rem;
}
.max-w-sm {
max-width: 24rem;
}
.max-w-xs {
max-width: 20rem;
}
.max-w-xl {
max-width: 36rem;
}
.max-w-lg {
max-width: 32rem;
}
.flex-1 {
flex: 1 1 0%;
}
@ -953,6 +993,10 @@ body {
justify-content: space-between;
}
.gap-1\.5 {
gap: 0.375rem;
}
.gap-2 {
gap: 0.5rem;
}
@ -997,6 +1041,12 @@ body {
margin-bottom: calc(2rem * 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));
}
.overflow-auto {
overflow: auto;
}
@ -1102,6 +1152,10 @@ body {
background-color: hsl(var(--secondary) / var(--tw-bg-opacity));
}
.bg-transparent {
background-color: transparent;
}
.bg-white {
--tw-bg-opacity: 1;
background-color: rgb(255 255 255 / var(--tw-bg-opacity));
@ -1222,10 +1276,26 @@ body {
padding-bottom: 2rem;
}
.pl-10 {
padding-left: 2.5rem;
}
.pl-3 {
padding-left: 0.75rem;
}
.pl-6 {
padding-left: 1.5rem;
}
.pr-10 {
padding-right: 2.5rem;
}
.pr-3 {
padding-right: 0.75rem;
}
.pt-0 {
padding-top: 0px;
}
@ -1274,6 +1344,10 @@ body {
line-height: 1rem;
}
.text-\[0\.8rem\] {
font-size: 0.8rem;
}
.font-bold {
font-weight: 700;
}
@ -1312,6 +1386,11 @@ body {
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));
@ -1456,6 +1535,56 @@ body {
mask-image: linear-gradient(180deg,white,rgba(255,255,255,0));
}
.file\:mr-4::file-selector-button {
margin-right: 1rem;
}
.file\:rounded-md::file-selector-button {
border-radius: calc(var(--radius) - 2px);
}
.file\:border-0::file-selector-button {
border-width: 0px;
}
.file\:bg-transparent::file-selector-button {
background-color: transparent;
}
.file\:bg-secondary::file-selector-button {
--tw-bg-opacity: 1;
background-color: hsl(var(--secondary) / var(--tw-bg-opacity));
}
.file\:px-4::file-selector-button {
padding-left: 1rem;
padding-right: 1rem;
}
.file\:py-2::file-selector-button {
padding-top: 0.5rem;
padding-bottom: 0.5rem;
}
.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-secondary-foreground::file-selector-button {
--tw-text-opacity: 1;
color: hsl(var(--secondary-foreground) / var(--tw-text-opacity));
}
.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));
@ -1522,6 +1651,10 @@ body {
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
}
.hover\:file\:bg-secondary\/80::file-selector-button:hover {
background-color: hsl(var(--secondary) / 0.8);
}
.focus\:border-ring:focus {
--tw-border-opacity: 1;
border-color: hsl(var(--ring) / var(--tw-border-opacity));
@ -1561,6 +1694,12 @@ body {
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-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);
@ -1640,6 +1779,11 @@ body {
color: rgb(255 255 255 / 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));

View File

@ -25,6 +25,7 @@ func main() {
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/card", templ.Handler(pages.Card()))
mux.Handle("GET /docs/components/input", templ.Handler(pages.Input()))
fmt.Println("Server is running on http://localhost:8090")
http.ListenAndServe(":8090", mux)

View File

@ -37,6 +37,10 @@ var Sections = []Section{
Text: "Card",
Href: "/docs/components/card",
},
{
Text: "Input",
Href: "/docs/components/input",
},
{
Text: "Sheet",
Href: "/docs/components/sheet",

View File

@ -0,0 +1,43 @@
package components
type InputProps struct {
Type string
Placeholder string
Value string
Name string
ID string
Class string
Disabled any
ReadOnly bool
Required bool
FileAccept string
Attributes templ.Attributes
}
templ Input(props InputProps) {
<input
type={ props.Type }
placeholder={ props.Placeholder }
value={ props.Value }
name={ props.Name }
id={ props.ID }
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", "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 }
}
}
readonly?={ props.ReadOnly }
required?={ props.Required }
if props.Type == "file" {
accept={ props.FileAccept }
}
{ props.Attributes... }
/>
}

View File

@ -0,0 +1,36 @@
package pages
import (
"github.com/axzilla/goilerplate/internals/ui/components"
"github.com/axzilla/goilerplate/internals/ui/layouts"
"github.com/axzilla/goilerplate/internals/ui/showcase"
)
templ Input() {
@layouts.DocsLayout() {
<div class="mb-16">
<h1 class="text-3xl font-bold mb-2">Input</h1>
<p class="mb-4 text-muted-foreground">Displays a form input field or a component that looks like an input field.</p>
</div>
@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",
})
}
}

View File

@ -0,0 +1,78 @@
package showcase
import "github.com/axzilla/goilerplate/internals/ui/components"
templ InputShowcase() {
<div class="flex justify-center items-center border rounded-md py-16 px-4">
<div>
<div class="mb-8">
<h2 class="font-semibold mb-2">Default</h2>
@components.Input(components.InputProps{
Type: "email",
Placeholder: "Email",
})
</div>
<div class="mb-8">
<h2 class="font-semibold mb-2">File</h2>
<div class="grid w-full max-w-sm items-center gap-1.5">
@components.Input(components.InputProps{
Type: "file",
})
</div>
</div>
<div class="mb-8">
<h2 class="font-semibold mb-2">Disabled</h2>
@components.Input(components.InputProps{
Type: "email",
Placeholder: "Email",
Disabled: "true",
})
</div>
<div class="mb-8">
<h2 class="font-semibold mb-2">With Label</h2>
<div class="grid w-full max-w-sm items-center gap-1.5">
<label for="email" class="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70">
Email
</label>
@components.Input(components.InputProps{
ID: "email",
Type: "email",
Placeholder: "Email",
})
</div>
</div>
<div class="mb-8">
<h2 class="font-semibold mb-2">With Button</h2>
<div class="flex w-full max-w-sm items-center space-x-2">
@components.Input(components.InputProps{
Type: "email",
Placeholder: "Email",
})
@components.Button(components.ButtonProps{
Type: "submit",
Text: "Subscribe",
})
</div>
</div>
<div class="mb-8">
<h2 class="font-semibold mb-2">Form</h2>
<form class="w-full max-w-sm space-y-6">
<div class="space-y-2">
<label for="username" class="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70">
Username
</label>
@components.Input(components.InputProps{
ID: "username",
Type: "text",
})
<p class="text-sm text-muted-foreground m-0">This is your public display name.</p>
</div>
@components.Button(components.ButtonProps{
Type: "submit",
Text: "Submit",
})
</form>
</div>
</div>
</div>
}