mirror of
https://github.com/axzilla/templui.git
synced 2025-02-21 00:32:58 +00:00
refactor: clean up unused CSS classes and improve toast handler structure
This commit is contained in:
parent
0bc679826c
commit
b8612c352c
@ -788,10 +788,6 @@ body {
|
||||
margin-left: 0.75rem;
|
||||
}
|
||||
|
||||
.ml-4 {
|
||||
margin-left: 1rem;
|
||||
}
|
||||
|
||||
.ml-auto {
|
||||
margin-left: auto;
|
||||
}
|
||||
@ -1443,11 +1439,6 @@ body {
|
||||
background-color: hsl(var(--destructive) / var(--tw-bg-opacity, 1));
|
||||
}
|
||||
|
||||
.bg-gray-50 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(249 250 251 / var(--tw-bg-opacity, 1));
|
||||
}
|
||||
|
||||
.bg-gray-700 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(55 65 81 / var(--tw-bg-opacity, 1));
|
||||
|
@ -13,21 +13,13 @@ import (
|
||||
"github.com/axzilla/templui/pkg/components"
|
||||
)
|
||||
|
||||
func HandleToastDemo(w http.ResponseWriter, r *http.Request) {
|
||||
func toastDemoHandler(w http.ResponseWriter, r *http.Request) {
|
||||
duration, err := strconv.Atoi(r.FormValue("duration"))
|
||||
if err != nil {
|
||||
duration = 0
|
||||
}
|
||||
fmt.Println("duration", duration)
|
||||
fmt.Println("r.FormValue(\"message\")", r.FormValue("message"))
|
||||
fmt.Println("r.FormValue(\"type\")", r.FormValue("type"))
|
||||
fmt.Println("r.FormValue(\"position\")", r.FormValue("position"))
|
||||
fmt.Println("r.FormValue(\"theme\")", r.FormValue("theme"))
|
||||
fmt.Println("r.FormValue(\"size\")", r.FormValue("size"))
|
||||
fmt.Println("r.FormValue(\"dismissible\")", r.FormValue("dismissible"))
|
||||
fmt.Println("r.FormValue(\"icon\")", r.FormValue("icon"))
|
||||
|
||||
cfg := components.ToastProps{
|
||||
toastProps := components.ToastProps{
|
||||
Message: r.FormValue("message"),
|
||||
Type: r.FormValue("type"),
|
||||
Position: r.FormValue("position"),
|
||||
@ -37,38 +29,7 @@ func HandleToastDemo(w http.ResponseWriter, r *http.Request) {
|
||||
Icon: r.FormValue("icon") == "on",
|
||||
}
|
||||
|
||||
components.Toast(cfg).Render(r.Context(), w)
|
||||
return
|
||||
}
|
||||
|
||||
func HandleCreateUser(w http.ResponseWriter, r *http.Request) {
|
||||
email := r.FormValue("email")
|
||||
|
||||
// Validierung
|
||||
if email == "" {
|
||||
// Error Toast
|
||||
components.Toast(components.ToastProps{
|
||||
Message: "Email ist erforderlich",
|
||||
Type: "error",
|
||||
Position: "top-left",
|
||||
Duration: 1000,
|
||||
Dismissible: true,
|
||||
Size: "md",
|
||||
Icon: true,
|
||||
}).Render(r.Context(), w)
|
||||
return
|
||||
}
|
||||
|
||||
// Erfolg Toast
|
||||
components.Toast(components.ToastProps{
|
||||
Message: "Benutzer erstellt",
|
||||
Type: "success",
|
||||
Position: "bottom-right",
|
||||
Duration: 3000,
|
||||
Dismissible: false,
|
||||
Size: "sm",
|
||||
Icon: true,
|
||||
}).Render(r.Context(), w)
|
||||
components.Toast(toastProps).Render(r.Context(), w)
|
||||
}
|
||||
|
||||
func main() {
|
||||
@ -108,8 +69,7 @@ func main() {
|
||||
mux.Handle("GET /docs/components/toast", templ.Handler(pages.Toast()))
|
||||
mux.Handle("GET /docs/components/toggle", templ.Handler(pages.Toggle()))
|
||||
// Showcase API
|
||||
mux.Handle("POST /users", http.HandlerFunc(HandleCreateUser))
|
||||
mux.Handle("POST /docs/toast/demo", http.HandlerFunc(HandleToastDemo))
|
||||
mux.Handle("POST /docs/toast/demo", http.HandlerFunc(toastDemoHandler))
|
||||
|
||||
fmt.Println("Server is running on http://localhost:8090")
|
||||
http.ListenAndServe(":8090", wrappedMux)
|
||||
|
@ -33,7 +33,6 @@ templ ExampleWrapper(p ExampleWrapperProps) {
|
||||
</div>
|
||||
}
|
||||
|
||||
// generateTabs erstellt die Tabs basierend auf den Props
|
||||
func generateTabs(p ExampleWrapperProps) []components.Tab {
|
||||
tabs := []components.Tab{
|
||||
{
|
||||
@ -50,7 +49,6 @@ func generateTabs(p ExampleWrapperProps) []components.Tab {
|
||||
},
|
||||
}
|
||||
|
||||
// Füge Component Tab nur hinzu wenn gewünscht
|
||||
if p.ComponentCodeFile != "" {
|
||||
tabs = append(tabs, components.Tab{
|
||||
ID: "component",
|
||||
|
@ -1,27 +1,90 @@
|
||||
package pages
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/axzilla/templui/internals/ui/layouts"
|
||||
"github.com/axzilla/templui/internals/ui/modules"
|
||||
"github.com/axzilla/templui/internals/ui/showcase"
|
||||
"github.com/axzilla/templui/pkg/components"
|
||||
)
|
||||
|
||||
templ Toast() {
|
||||
@layouts.DocsLayout() {
|
||||
@modules.PageWrapper(modules.PageWrapperProps{
|
||||
Name: "Toast",
|
||||
Description: templ.Raw("Flexible Toast component for notifications and feedback."),
|
||||
Description: templ.Raw("Flexible toast component for notifications and feedback."),
|
||||
}) {
|
||||
// @modules.ExampleWrapper(modules.ExampleWrapperProps{
|
||||
// ShowcaseFile: showcase.Toast(),
|
||||
// PreviewCodeFile: "toast.templ",
|
||||
// ComponentCodeFile: "toast.templ",
|
||||
// })
|
||||
@modules.ExampleWrapper(modules.ExampleWrapperProps{
|
||||
ShowcaseFile: showcase.ToastAdvanced(),
|
||||
PreviewCodeFile: "toast_advancded.templ",
|
||||
ShowcaseFile: showcase.Toast(),
|
||||
PreviewCodeFile: "toast.templ",
|
||||
ComponentCodeFile: "toast.templ",
|
||||
})
|
||||
@UsageExamples()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
templ UsageExamples() {
|
||||
@components.Tabs(components.TabsProps{
|
||||
Tabs: []components.Tab{
|
||||
{
|
||||
ID: "with-htmx",
|
||||
Title: "With HTMX",
|
||||
Content: withHtmx(),
|
||||
},
|
||||
{
|
||||
ID: "full-page-form",
|
||||
Title: "Full Page Form",
|
||||
Content: fullPageForm(),
|
||||
},
|
||||
},
|
||||
TabsContainerClass: "w-full",
|
||||
ContentContainerClass: "w-full",
|
||||
})
|
||||
}
|
||||
|
||||
var withHtmxCode = fmt.Sprintf(`// Template
|
||||
%s UserForm() {
|
||||
<form hx-post="/save" hx-target="#toast">
|
||||
<input name="email" />
|
||||
</form>
|
||||
<div id="toast"></div>
|
||||
}
|
||||
|
||||
// Handler
|
||||
func Save(w http.ResponseWriter, r *http.Request) {
|
||||
if err != nil {
|
||||
components.Toast(components.ToastProps{
|
||||
Message: err.Error(),
|
||||
Type: "error",
|
||||
}).Render(r.Context(), w)
|
||||
}
|
||||
}`, "templ")
|
||||
|
||||
templ withHtmx() {
|
||||
@modules.CodeSnippet(withHtmxCode, "go")
|
||||
}
|
||||
|
||||
var fullPageFormCode = fmt.Sprintf(`// Template
|
||||
%s UserForm(error string) {
|
||||
if error != "" {
|
||||
@components.Toast(components.ToastProps{
|
||||
Message: error,
|
||||
Type: "error",
|
||||
})
|
||||
}
|
||||
<form method="POST">
|
||||
<input name="email"/>
|
||||
</form>
|
||||
}
|
||||
|
||||
// Handler
|
||||
func Save(w http.ResponseWriter, r *http.Request) {
|
||||
if err != nil {
|
||||
UserForm(err.Error()).Render(r.Context(), w)
|
||||
}
|
||||
}`, "templ")
|
||||
|
||||
templ fullPageForm() {
|
||||
@modules.CodeSnippet(string(fullPageFormCode), "go")
|
||||
}
|
||||
|
@ -1,25 +1,104 @@
|
||||
package showcase
|
||||
|
||||
import "github.com/axzilla/templui/pkg/components"
|
||||
|
||||
templ Toast() {
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<div>
|
||||
<form
|
||||
hx-post="/users"
|
||||
hx-target="#toast-container"
|
||||
class="space-y-4"
|
||||
>
|
||||
<div>
|
||||
<label for="email">Email</label>
|
||||
<input
|
||||
type="email"
|
||||
name="email"
|
||||
id="email"
|
||||
class="w-full rounded-lg border"
|
||||
/>
|
||||
</div>
|
||||
<button type="submit">Speichern</button>
|
||||
</form>
|
||||
<div id="toast-container"></div>
|
||||
</div>
|
||||
<div class="w-full max-w-4xl mx-auto p-8">
|
||||
<section class="mb-12">
|
||||
@components.Card(components.CardProps{}) {
|
||||
@components.CardContent() {
|
||||
<form
|
||||
class="flex flex-col gap-2"
|
||||
hx-post="/docs/toast/demo"
|
||||
hx-trigger="submit"
|
||||
hx-target="#toast-container"
|
||||
>
|
||||
// Message
|
||||
@components.FormItem(components.FormItemProps{}) {
|
||||
@components.Label(components.LabelProps{Text: "Message"})
|
||||
@components.Input(components.InputProps{
|
||||
Value: "Test Notification",
|
||||
Name: "message",
|
||||
})
|
||||
}
|
||||
// Type
|
||||
@components.FormItem(components.FormItemProps{}) {
|
||||
@components.Label(components.LabelProps{Text: "Type"})
|
||||
@components.Select(components.SelectProps{
|
||||
Name: "type",
|
||||
Options: []components.SelectOption{
|
||||
{Value: "default", Label: "Default"},
|
||||
{Value: "success", Label: "Success"},
|
||||
{Value: "error", Label: "Error"},
|
||||
{Value: "warning", Label: "Warning"},
|
||||
{Value: "info", Label: "Info"},
|
||||
},
|
||||
})
|
||||
}
|
||||
// Position
|
||||
@components.FormItem(components.FormItemProps{}) {
|
||||
@components.Label(components.LabelProps{Text: "Position"})
|
||||
@components.Select(components.SelectProps{
|
||||
Name: "position",
|
||||
Options: []components.SelectOption{
|
||||
{Value: "top-right", Label: "Top Right"},
|
||||
{Value: "top-left", Label: "Top Left"},
|
||||
{Value: "top-center", Label: "Top Center"},
|
||||
{Value: "bottom-right", Label: "Bottom Right", Selected: true},
|
||||
{Value: "bottom-left", Label: "Bottom Left"},
|
||||
{Value: "bottom-center", Label: "Bottom Center"},
|
||||
},
|
||||
})
|
||||
}
|
||||
// Duration
|
||||
@components.FormItem(components.FormItemProps{}) {
|
||||
@components.Label(components.LabelProps{Text: "Duration (ms)"})
|
||||
@components.Input(components.InputProps{
|
||||
Type: "number",
|
||||
Name: "duration",
|
||||
Value: "3000",
|
||||
})
|
||||
}
|
||||
// Size
|
||||
@components.FormItem(components.FormItemProps{}) {
|
||||
@components.Label(components.LabelProps{Text: "Size"})
|
||||
@components.Select(components.SelectProps{
|
||||
Name: "size",
|
||||
Options: []components.SelectOption{
|
||||
{Value: "sm", Label: "Small"},
|
||||
{Value: "md", Label: "Medium"},
|
||||
{Value: "lg", Label: "Large"},
|
||||
},
|
||||
})
|
||||
}
|
||||
// Options
|
||||
@components.FormItem(components.FormItemProps{}) {
|
||||
@components.Label(components.LabelProps{Text: "Options"})
|
||||
@components.FormItemFlex(components.FormItemProps{}) {
|
||||
@components.Toggle(components.ToggleProps{
|
||||
Name: "dismissible",
|
||||
Checked: true,
|
||||
})
|
||||
@components.Label(components.LabelProps{Text: "Dismissible"})
|
||||
}
|
||||
@components.FormItemFlex(components.FormItemProps{}) {
|
||||
@components.Toggle(components.ToggleProps{
|
||||
Name: "icon",
|
||||
Checked: true,
|
||||
})
|
||||
@components.Label(components.LabelProps{Text: "Show Icon"})
|
||||
}
|
||||
}
|
||||
// Submit
|
||||
@components.Button(components.ButtonProps{
|
||||
Text: "Show Toast",
|
||||
Type: "submit",
|
||||
Class: "w-full",
|
||||
})
|
||||
</form>
|
||||
}
|
||||
}
|
||||
</section>
|
||||
<div id="toast-container"></div>
|
||||
</div>
|
||||
}
|
||||
|
@ -1,139 +0,0 @@
|
||||
package showcase
|
||||
|
||||
import "github.com/axzilla/templui/pkg/components"
|
||||
|
||||
templ ToastAdvanced() {
|
||||
<div class="max-w-4xl mx-auto p-8">
|
||||
<section class="mb-12">
|
||||
@components.Card(components.CardProps{}) {
|
||||
@components.CardContent() {
|
||||
<form
|
||||
class="flex flex-col gap-2"
|
||||
hx-post="/docs/toast/demo"
|
||||
hx-trigger="change, submit"
|
||||
hx-target="#toast-containerx"
|
||||
>
|
||||
// Message
|
||||
@components.FormItem(components.FormItemProps{}) {
|
||||
@components.Label(components.LabelProps{Text: "Message"})
|
||||
@components.Input(components.InputProps{
|
||||
Value: "Test Notification",
|
||||
Name: "message",
|
||||
})
|
||||
}
|
||||
// Type
|
||||
@components.FormItem(components.FormItemProps{}) {
|
||||
@components.Label(components.LabelProps{Text: "Type"})
|
||||
@components.Select(components.SelectProps{
|
||||
Name: "type",
|
||||
Options: []components.SelectOption{
|
||||
{Value: "default", Label: "Default"},
|
||||
{Value: "success", Label: "Success"},
|
||||
{Value: "error", Label: "Error"},
|
||||
{Value: "warning", Label: "Warning"},
|
||||
{Value: "info", Label: "Info"},
|
||||
},
|
||||
})
|
||||
}
|
||||
// Position
|
||||
@components.FormItem(components.FormItemProps{}) {
|
||||
@components.Label(components.LabelProps{Text: "Position"})
|
||||
@components.Select(components.SelectProps{
|
||||
Name: "position",
|
||||
Options: []components.SelectOption{
|
||||
{Value: "top-right", Label: "Top Right"},
|
||||
{Value: "top-left", Label: "Top Left"},
|
||||
{Value: "top-center", Label: "Top Center"},
|
||||
{Value: "bottom-right", Label: "Bottom Right"},
|
||||
{Value: "bottom-left", Label: "Bottom Left"},
|
||||
{Value: "bottom-center", Label: "Bottom Center"},
|
||||
},
|
||||
})
|
||||
}
|
||||
// Duration
|
||||
@components.FormItem(components.FormItemProps{}) {
|
||||
@components.Label(components.LabelProps{Text: "Duration (ms)"})
|
||||
@components.Input(components.InputProps{
|
||||
Type: "number",
|
||||
Name: "duration",
|
||||
Value: "3000",
|
||||
})
|
||||
}
|
||||
// Size
|
||||
@components.FormItem(components.FormItemProps{}) {
|
||||
@components.Label(components.LabelProps{Text: "Size"})
|
||||
@components.Select(components.SelectProps{
|
||||
Name: "size",
|
||||
Options: []components.SelectOption{
|
||||
{Value: "sm", Label: "Small"},
|
||||
{Value: "md", Label: "Medium"},
|
||||
{Value: "lg", Label: "Large"},
|
||||
},
|
||||
})
|
||||
}
|
||||
// Options
|
||||
@components.FormItem(components.FormItemProps{}) {
|
||||
@components.Label(components.LabelProps{Text: "Options"})
|
||||
@components.FormItemFlex(components.FormItemProps{}) {
|
||||
@components.Toggle(components.ToggleProps{
|
||||
Name: "dismissible",
|
||||
Checked: true,
|
||||
})
|
||||
@components.Label(components.LabelProps{Text: "Dismissible"})
|
||||
}
|
||||
@components.FormItemFlex(components.FormItemProps{}) {
|
||||
@components.Toggle(components.ToggleProps{
|
||||
Name: "icon",
|
||||
Checked: true,
|
||||
})
|
||||
@components.Label(components.LabelProps{Text: "Show Icon"})
|
||||
}
|
||||
}
|
||||
@components.Button(components.ButtonProps{
|
||||
Text: "Show Toast",
|
||||
Type: "submit",
|
||||
Class: "w-full",
|
||||
})
|
||||
</form>
|
||||
}
|
||||
}
|
||||
</section>
|
||||
<div id="toast-containerx"></div>
|
||||
// Code Examples
|
||||
<section>
|
||||
<h2 class="text-xl font-semibold mb-4">Usage Examples</h2>
|
||||
<div class="space-y-4">
|
||||
<div class="p-4 bg-gray-50 rounded-lg">
|
||||
<h3 class="font-medium mb-2">Basic Usage</h3>
|
||||
<pre class="text-sm">
|
||||
{ `// In your handler
|
||||
components.Toast(types.ToastConfig{
|
||||
Message: "Nachricht",
|
||||
Type: "success",
|
||||
Position: "top-right",
|
||||
Duration: 3000,
|
||||
}).Render(ctx, w)` }
|
||||
</pre>
|
||||
</div>
|
||||
<div class="p-4 bg-gray-50 rounded-lg">
|
||||
<h3 class="font-medium mb-2">With HTMX</h3>
|
||||
<pre class="text-sm">
|
||||
{ `// Template
|
||||
<form hx-post="/save" hx-target="#toast-container">
|
||||
...
|
||||
</form>
|
||||
<div id="toast-container"></div>
|
||||
|
||||
// Handler
|
||||
if err != nil {
|
||||
return components.Toast(types.ToastConfig{
|
||||
Message: err.Error(),
|
||||
Type: "error",
|
||||
}).Render(ctx, w)
|
||||
}` }
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
}
|
@ -6,26 +6,26 @@ import (
|
||||
)
|
||||
|
||||
type ToastProps struct {
|
||||
Message string // Die Nachricht
|
||||
Type string // success, error, warning, info, default
|
||||
Position string // top-right, top-left, top-center, bottom-right, bottom-left, bottom-center
|
||||
Duration int // Millisekunden, 0 = permanent
|
||||
Dismissible bool // Kann manuell geschlossen werden
|
||||
Size string // sm, md, lg
|
||||
Icon bool // Icon anzeigen/verstecken
|
||||
HTML string // Custom HTML Content
|
||||
Message string // Message to display
|
||||
Type string // Type of the toast (default, success, error, warning, info)
|
||||
Position string // Position of the toast (top-right, top-left, top-center, bottom-right, bottom-left, bottom-center)
|
||||
Duration int // Duration in milliseconds
|
||||
Dismissible bool // Show dismiss button
|
||||
Size string // Size of the toast (sm, md, lg)
|
||||
Icon bool // Show icon
|
||||
}
|
||||
|
||||
templ Toast(cfg ToastProps) {
|
||||
// Flexible toast component for notifications and feedback.
|
||||
templ Toast(props ToastProps) {
|
||||
<div
|
||||
x-data={ `{
|
||||
show: true,
|
||||
message: '` + cfg.Message + `',
|
||||
type: '` + cfg.Type + `',
|
||||
position: '` + cfg.Position + `',
|
||||
duration: ` + fmt.Sprint(cfg.Duration) + `,
|
||||
dismissible: ` + fmt.Sprint(cfg.Dismissible) + `,
|
||||
size: '` + cfg.Size + `'
|
||||
message: '` + props.Message + `',
|
||||
type: '` + props.Type + `',
|
||||
position: '` + props.Position + `',
|
||||
duration: ` + fmt.Sprint(props.Duration) + `,
|
||||
dismissible: ` + fmt.Sprint(props.Dismissible) + `,
|
||||
size: '` + props.Size + `'
|
||||
}` }
|
||||
x-init="if(duration > 0) setTimeout(() => show = false, duration)"
|
||||
x-show="show"
|
||||
@ -36,7 +36,7 @@ templ Toast(cfg ToastProps) {
|
||||
x-transition:leave-start="opacity-100 translate-y-0"
|
||||
x-transition:leave-end="opacity-0 translate-y-4"
|
||||
@click="if(dismissible) show = false"
|
||||
class="fixed pointer-events-auto"
|
||||
class="z-50 fixed pointer-events-auto"
|
||||
:class="{
|
||||
// Position
|
||||
'top-4 right-4': position === 'top-right',
|
||||
@ -51,43 +51,34 @@ templ Toast(cfg ToastProps) {
|
||||
'w-[30rem]': size === 'lg'
|
||||
}"
|
||||
>
|
||||
if cfg.HTML != "" {
|
||||
<div
|
||||
x-html="message"
|
||||
class="rounded-lg shadow-lg"
|
||||
></div>
|
||||
} else {
|
||||
// Default Toast
|
||||
<div
|
||||
class="bg-primary-foreground rounded-lg shadow-sm border p-4 flex items-center justify-center"
|
||||
>
|
||||
if cfg.Icon {
|
||||
// Icons für verschiedene Types
|
||||
if cfg.Type == "success" {
|
||||
@icons.CircleCheck(icons.IconProps{Size: "18", Class: "text-green-500 mr-3"})
|
||||
}
|
||||
if cfg.Type == "error" {
|
||||
@icons.CircleX(icons.IconProps{Size: "18", Class: "text-red-500 mr-3"})
|
||||
}
|
||||
if cfg.Type == "warning" {
|
||||
@icons.TriangleAlert(icons.IconProps{Size: "18", Class: "text-yellow-500 mr-3"})
|
||||
}
|
||||
if cfg.Type == "info" {
|
||||
@icons.Info(icons.IconProps{Size: "18", Class: "text-blue-500 mr-3"})
|
||||
}
|
||||
<div
|
||||
class="bg-primary-foreground rounded-lg shadow-sm border p-4 flex items-center justify-center"
|
||||
>
|
||||
if props.Icon {
|
||||
if props.Type == "success" {
|
||||
@icons.CircleCheck(icons.IconProps{Size: "18", Class: "text-green-500 mr-3"})
|
||||
}
|
||||
<div class="flex-1" x-text="message"></div>
|
||||
if cfg.Dismissible {
|
||||
<button
|
||||
@click.stop="show = false"
|
||||
>
|
||||
@icons.X(icons.IconProps{
|
||||
Size: "18",
|
||||
Class: "ml-4 flex-shrink-0 opacity-75 hover:opacity-100",
|
||||
})
|
||||
</button>
|
||||
if props.Type == "error" {
|
||||
@icons.CircleX(icons.IconProps{Size: "18", Class: "text-red-500 mr-3"})
|
||||
}
|
||||
</div>
|
||||
}
|
||||
if props.Type == "warning" {
|
||||
@icons.TriangleAlert(icons.IconProps{Size: "18", Class: "text-yellow-500 mr-3"})
|
||||
}
|
||||
if props.Type == "info" {
|
||||
@icons.Info(icons.IconProps{Size: "18", Class: "text-blue-500 mr-3"})
|
||||
}
|
||||
}
|
||||
<div class="flex-1" x-text="message"></div>
|
||||
if props.Dismissible {
|
||||
<button
|
||||
@click.stop="show = false"
|
||||
>
|
||||
@icons.X(icons.IconProps{
|
||||
Size: "18",
|
||||
Class: "opacity-75 hover:opacity-100",
|
||||
})
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
@ -14,17 +14,17 @@ import (
|
||||
)
|
||||
|
||||
type ToastProps struct {
|
||||
Message string // Die Nachricht
|
||||
Type string // success, error, warning, info, default
|
||||
Position string // top-right, top-left, top-center, bottom-right, bottom-left, bottom-center
|
||||
Duration int // Millisekunden, 0 = permanent
|
||||
Dismissible bool // Kann manuell geschlossen werden
|
||||
Size string // sm, md, lg
|
||||
Icon bool // Icon anzeigen/verstecken
|
||||
HTML string // Custom HTML Content
|
||||
Message string // Message to display
|
||||
Type string // Type of the toast (default, success, error, warning, info)
|
||||
Position string // Position of the toast (top-right, top-left, top-center, bottom-right, bottom-left, bottom-center)
|
||||
Duration int // Duration in milliseconds
|
||||
Dismissible bool // Show dismiss button
|
||||
Size string // Size of the toast (sm, md, lg)
|
||||
Icon bool // Show icon
|
||||
}
|
||||
|
||||
func Toast(cfg ToastProps) templ.Component {
|
||||
// Flexible toast component for notifications and feedback.
|
||||
func Toast(props ToastProps) 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 {
|
||||
@ -52,12 +52,12 @@ func Toast(cfg ToastProps) templ.Component {
|
||||
var templ_7745c5c3_Var2 string
|
||||
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(`{
|
||||
show: true,
|
||||
message: '` + cfg.Message + `',
|
||||
type: '` + cfg.Type + `',
|
||||
position: '` + cfg.Position + `',
|
||||
duration: ` + fmt.Sprint(cfg.Duration) + `,
|
||||
dismissible: ` + fmt.Sprint(cfg.Dismissible) + `,
|
||||
size: '` + cfg.Size + `'
|
||||
message: '` + props.Message + `',
|
||||
type: '` + props.Type + `',
|
||||
position: '` + props.Position + `',
|
||||
duration: ` + fmt.Sprint(props.Duration) + `,
|
||||
dismissible: ` + fmt.Sprint(props.Dismissible) + `,
|
||||
size: '` + props.Size + `'
|
||||
}`)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/components/toast.templ`, Line: 29, Col: 10}
|
||||
@ -66,89 +66,70 @@ func Toast(cfg ToastProps) templ.Component {
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" x-init=\"if(duration > 0) setTimeout(() => show = false, duration)\" x-show=\"show\" x-transition:enter=\"transition ease-out duration-300\" x-transition:enter-start=\"opacity-0 translate-y-4\" x-transition:enter-end=\"opacity-100 translate-y-0\" x-transition:leave=\"transition ease-in duration-200\" x-transition:leave-start=\"opacity-100 translate-y-0\" x-transition:leave-end=\"opacity-0 translate-y-4\" @click=\"if(dismissible) show = false\" class=\"fixed pointer-events-auto\" :class=\"{\n // Position\n 'top-4 right-4': position === 'top-right',\n 'top-4 left-4': position === 'top-left',\n 'top-4 left-1/2 -translate-x-1/2': position === 'top-center',\n 'bottom-4 right-4': position === 'bottom-right',\n 'bottom-4 left-4': position === 'bottom-left',\n 'bottom-4 left-1/2 -translate-x-1/2': position === 'bottom-center',\n // Size\n 'w-72': size === 'sm',\n 'w-96': size === 'md',\n 'w-[30rem]': size === 'lg'\n }\">")
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" x-init=\"if(duration > 0) setTimeout(() => show = false, duration)\" x-show=\"show\" x-transition:enter=\"transition ease-out duration-300\" x-transition:enter-start=\"opacity-0 translate-y-4\" x-transition:enter-end=\"opacity-100 translate-y-0\" x-transition:leave=\"transition ease-in duration-200\" x-transition:leave-start=\"opacity-100 translate-y-0\" x-transition:leave-end=\"opacity-0 translate-y-4\" @click=\"if(dismissible) show = false\" class=\"z-50 fixed pointer-events-auto\" :class=\"{\n // Position\n 'top-4 right-4': position === 'top-right',\n 'top-4 left-4': position === 'top-left',\n 'top-4 left-1/2 -translate-x-1/2': position === 'top-center',\n 'bottom-4 right-4': position === 'bottom-right',\n 'bottom-4 left-4': position === 'bottom-left',\n 'bottom-4 left-1/2 -translate-x-1/2': position === 'bottom-center',\n // Size\n 'w-72': size === 'sm',\n 'w-96': size === 'md',\n 'w-[30rem]': size === 'lg'\n }\"><div class=\"bg-primary-foreground rounded-lg shadow-sm border p-4 flex items-center justify-center\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
if cfg.HTML != "" {
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div x-html=\"message\" class=\"rounded-lg shadow-lg\"></div>")
|
||||
if props.Icon {
|
||||
if props.Type == "success" {
|
||||
templ_7745c5c3_Err = icons.CircleCheck(icons.IconProps{Size: "18", Class: "text-green-500 mr-3"}).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(" <div class=\"bg-primary-foreground rounded-lg shadow-sm border p-4 flex items-center justify-center\">")
|
||||
if props.Type == "error" {
|
||||
templ_7745c5c3_Err = icons.CircleX(icons.IconProps{Size: "18", Class: "text-red-500 mr-3"}).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 cfg.Icon {
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ")
|
||||
if props.Type == "warning" {
|
||||
templ_7745c5c3_Err = icons.TriangleAlert(icons.IconProps{Size: "18", Class: "text-yellow-500 mr-3"}).Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
if cfg.Type == "success" {
|
||||
templ_7745c5c3_Err = icons.CircleCheck(icons.IconProps{Size: "18", Class: "text-green-500 mr-3"}).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 cfg.Type == "error" {
|
||||
templ_7745c5c3_Err = icons.CircleX(icons.IconProps{Size: "18", Class: "text-red-500 mr-3"}).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 cfg.Type == "warning" {
|
||||
templ_7745c5c3_Err = icons.TriangleAlert(icons.IconProps{Size: "18", Class: "text-yellow-500 mr-3"}).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 cfg.Type == "info" {
|
||||
templ_7745c5c3_Err = icons.Info(icons.IconProps{Size: "18", Class: "text-blue-500 mr-3"}).Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"flex-1\" x-text=\"message\"></div>")
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
if cfg.Dismissible {
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<button @click.stop=\"show = false\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = icons.X(icons.IconProps{
|
||||
Size: "18",
|
||||
Class: "ml-4 flex-shrink-0 opacity-75 hover:opacity-100",
|
||||
}).Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</button>")
|
||||
if props.Type == "info" {
|
||||
templ_7745c5c3_Err = icons.Info(icons.IconProps{Size: "18", Class: "text-blue-500 mr-3"}).Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>")
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"flex-1\" x-text=\"message\"></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
if props.Dismissible {
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<button @click.stop=\"show = false\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = icons.X(icons.IconProps{
|
||||
Size: "18",
|
||||
Class: "opacity-75 hover:opacity-100",
|
||||
}).Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</button>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>")
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user