package catalog import ( "context" "io" "github.com/a-h/templ" "backend/internal/web/ui" ) // Example is a single rendered component variant with a templ call annotation. type Example struct { Title string Preview templ.Component Snippet string } type anyComponent = templ.Component func badgeExamples() []Example { return []Example{ { Title: "Info", Preview: ui.Badge(ui.BadgeProps{ Label: "Info", Variant: ui.BadgeVariantInfo, }), Snippet: `@ui.Badge(ui.BadgeProps{Label: "Info", Variant: ui.BadgeVariantInfo})`, }, { Title: "Warning", Preview: ui.Badge(ui.BadgeProps{ Label: "Warning", Variant: ui.BadgeVariantWarning, }), Snippet: `@ui.Badge(ui.BadgeProps{Label: "Warning", Variant: ui.BadgeVariantWarning})`, }, { Title: "Success", Preview: ui.Badge(ui.BadgeProps{ Label: "Success", Variant: ui.BadgeVariantSuccess, }), Snippet: `@ui.Badge(ui.BadgeProps{Label: "Success", Variant: ui.BadgeVariantSuccess})`, }, { Title: "Danger", Preview: ui.Badge(ui.BadgeProps{ Label: "Danger", Variant: ui.BadgeVariantDanger, }), Snippet: `@ui.Badge(ui.BadgeProps{Label: "Danger", Variant: ui.BadgeVariantDanger})`, }, { Title: "Primary", Preview: ui.Badge(ui.BadgeProps{ Label: "Primary", Variant: ui.BadgeVariantPrimary, }), Snippet: `@ui.Badge(ui.BadgeProps{Label: "Primary", Variant: ui.BadgeVariantPrimary})`, }, } } func buttonExamples() []Example { return []Example{ { Title: "Solid / Default", Preview: ui.Button(ui.ButtonProps{ Label: "Create project", Variant: ui.ButtonVariantDefault, Tone: ui.ButtonToneSolid, Size: ui.SizeMD, Type: "button", }), Snippet: `@ui.Button(ui.ButtonProps{ Label: "Create project", Variant: ui.ButtonVariantDefault, Tone: ui.ButtonToneSolid, Size: ui.SizeMD, Type: "button", })`, }, { Title: "Solid / Danger", Preview: ui.Button(ui.ButtonProps{ Label: "Delete", Variant: ui.ButtonVariantDanger, Tone: ui.ButtonToneSolid, Size: ui.SizeMD, Type: "button", }), Snippet: `@ui.Button(ui.ButtonProps{ Label: "Delete", Variant: ui.ButtonVariantDanger, Tone: ui.ButtonToneSolid, Size: ui.SizeMD, Type: "button", })`, }, { Title: "Soft / Neutral", Preview: ui.Button(ui.ButtonProps{ Label: "Cancel", Variant: ui.ButtonVariantNeutral, Tone: ui.ButtonToneSoft, Size: ui.SizeMD, Type: "button", }), Snippet: `@ui.Button(ui.ButtonProps{ Label: "Cancel", Variant: ui.ButtonVariantNeutral, Tone: ui.ButtonToneSoft, Size: ui.SizeMD, Type: "button", })`, }, { Title: "Ghost", Preview: ui.Button(ui.ButtonProps{ Label: "Learn more", Variant: ui.ButtonVariantGhost, Size: ui.SizeMD, Type: "button", }), Snippet: `@ui.Button(ui.ButtonProps{ Label: "Learn more", Variant: ui.ButtonVariantGhost, Size: ui.SizeMD, Type: "button", })`, }, } } func cardExamples() []Example { return []Example{ { Title: "Card with header, body, and footer", Preview: ui.Card(ui.CardProps{ Header: textBody("Card Header"), Body: textBody("Card body content goes here."), Footer: textBody("Card Footer"), }), Snippet: `@ui.Card(ui.CardProps{ Header: headerComponent, Body: bodyComponent, Footer: footerComponent, })`, }, } } func emptyStateExamples() []Example { return []Example{ { Title: "Empty list", Preview: ui.EmptyState(ui.EmptyStateProps{ Title: "Nothing here yet", Description: "Add your first item to get started.", Icon: ui.UIIcon("grid3x3"), Action: ui.Button(ui.ButtonProps{ Label: "Add item", Variant: ui.ButtonVariantDefault, Tone: ui.ButtonToneSolid, Size: ui.SizeMD, Type: "button", Icon: "plus", }), }), Snippet: `@ui.EmptyState(ui.EmptyStateProps{ Title: "Nothing here yet", Description: "Add your first item to get started.", Icon: ui.UIIcon("grid3x3"), Action: ui.Button(...), })`, }, } } func formFieldExamples() []Example { return []Example{ { Title: "Field with label, hint, and error", Preview: ui.FormField(ui.FormFieldProps{ Label: "Project name", For: "catalog-name", Field: ui.Input(ui.InputProps{ ID: "catalog-name", Name: "name", Placeholder: "Enter a name", Type: "text", }), Hint: "Enter a value between 1 and 100.", Error: "This field is required.", }), Snippet: `@ui.FormField(ui.FormFieldProps{ Label: "Project name", For: "catalog-name", Field: ui.Input(ui.InputProps{...}), Hint: "Enter a value between 1 and 100.", Error: "This field is required.", })`, }, } } func iconButtonExamples() []Example { return []Example{ { Title: "Ghost / Neutral (plus icon)", Preview: ui.IconButton(ui.IconButtonProps{ Label: "Add item", Icon: "plus", Variant: ui.IconButtonVariantNeutral, Tone: ui.IconButtonToneGhost, Type: "button", }), Snippet: `@ui.IconButton(ui.IconButtonProps{ Label: "Add item", Icon: "plus", Variant: ui.IconButtonVariantNeutral, Tone: ui.IconButtonToneGhost, Type: "button", })`, }, { Title: "Solid / Danger (trash icon)", Preview: ui.IconButton(ui.IconButtonProps{ Label: "Delete item", Icon: "trash", Variant: ui.IconButtonVariantDanger, Tone: ui.IconButtonToneSolid, Type: "button", }), Snippet: `@ui.IconButton(ui.IconButtonProps{ Label: "Delete item", Icon: "trash", Variant: ui.IconButtonVariantDanger, Tone: ui.IconButtonToneSolid, Type: "button", })`, }, } } func inputExamples() []Example { return []Example{ { Title: "Text input", Preview: ui.Input(ui.InputProps{ Name: "name", Placeholder: "Enter text here", Type: "text", }), Snippet: `@ui.Input(ui.InputProps{ Name: "name", Placeholder: "Enter text here", Type: "text", })`, }, { Title: "Email input", Preview: ui.Input(ui.InputProps{ Name: "email", Placeholder: "you@example.com", Type: "email", }), Snippet: `@ui.Input(ui.InputProps{ Name: "email", Placeholder: "you@example.com", Type: "email", })`, }, } } func modalExamples() []Example { return []Example{ { Title: "Modal panel (no backdrop)", // Render only the panel div — not the full Modal component with backdrop. // Pitfall 7: ui-modal-backdrop is position:fixed and would overlay the catalog page. Preview: componentFunc(func(ctx context.Context, w io.Writer) error { _, err := io.WriteString(w, `
`) if err != nil { return err } if err := renderComponents(ctx, w, textBody(`

Confirm action

`), textBody(`

Are you sure you want to proceed?

`), textBody(`
`), ); err != nil { return err } if err := ui.Button(ui.ButtonProps{ Label: "Cancel", Variant: ui.ButtonVariantNeutral, Tone: ui.ButtonToneSoft, Size: ui.SizeMD, Type: "button", }).Render(ctx, w); err != nil { return err } if err := ui.Button(ui.ButtonProps{ Label: "Confirm", Variant: ui.ButtonVariantDefault, Tone: ui.ButtonToneSolid, Size: ui.SizeMD, Type: "button", }).Render(ctx, w); err != nil { return err } _, err = io.WriteString(w, `
`) return err }), Snippet: `@ui.Modal(ui.ModalProps{ Title: "Confirm action", Body: bodyContent, Actions: actionButtons, })`, }, } } func selectExamples() []Example { return []Example{ { Title: "Single select", Preview: ui.Select(ui.SelectProps{ Name: "status", Placeholder: "Select a status", Value: "in-progress", Options: []ui.SelectOption{ {Value: "todo", Label: "To do"}, {Value: "in-progress", Label: "In progress"}, {Value: "done", Label: "Done"}, }, }), Snippet: `@ui.Select(ui.SelectProps{ Name: "status", Placeholder: "Select a status", Value: "in-progress", Options: []ui.SelectOption{ {Value: "todo", Label: "To do"}, {Value: "in-progress", Label: "In progress"}, {Value: "done", Label: "Done"}, }, })`, }, } } func tableExamples() []Example { return []Example{ { Title: "Data table", Preview: ui.Table(ui.TableProps{ Head: textBody(`NameStatus`), Body: textBody(`Example ProjectIn progressAnother ProjectDone`), }), Snippet: `@ui.Table(ui.TableProps{ Head: tableHead, Body: tableBody, })`, }, } } func textareaExamples() []Example { return []Example{ { Title: "Textarea with placeholder", Preview: ui.Textarea(ui.TextareaProps{ Name: "description", Placeholder: "Enter a description...", Rows: 4, }), Snippet: `@ui.Textarea(ui.TextareaProps{ Name: "description", Placeholder: "Enter a description...", Rows: 4, })`, }, } } func componentFunc(fn func(context.Context, io.Writer) error) templ.Component { return templ.ComponentFunc(fn) } func textBody(text string) templ.Component { return templ.ComponentFunc(func(_ context.Context, w io.Writer) error { _, err := io.WriteString(w, text) return err }) } func renderComponents(ctx context.Context, w io.Writer, components ...templ.Component) error { for _, c := range components { if err := c.Render(ctx, w); err != nil { return err } } return nil }