Skip to content

How To - Design reusable UI components with HTMX #405

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
neuronishad opened this issue Jan 8, 2024 · 4 comments
Closed

How To - Design reusable UI components with HTMX #405

neuronishad opened this issue Jan 8, 2024 · 4 comments

Comments

@neuronishad
Copy link

Hello, sorry to post a question/discussion topic here, but I am trying to put together a stack ( go-templ, HTMX, tailwind CSS). As these technologies are not widely adopted yet, not many dedicated discussions places are available. So, I thought this might be the best place to ask for advice rather than reddit or stackoverflow

Ok, so I thought of making re-usable UI components for a project than I am building with above mentioned stack. What I mean by re-usable, its more or less similar to material UI components.

Now, this is totally possible, no issues in making it happen, but I wanted to address some inconveniences in developer experience.

Ex -

// Lets define a Button Component. I have a defined a primary color in tailwind-config.js as 'p-color'
templ Button(text string) {
    <button class="rounded w-20 text-center p-2 bg-p-color">{ text }</button>
}

Now we have a button component, lets say we want to add usability, but with HTMX and not JS attributes/actions

// JS version
templ Button(text string, onClick templ.ComponentScript) {
    <button class="rounded w-20 text-center p-2 bg-p-color" onclick={ onClick() }>{ text }</button>
}

// HTMX Version
templ Button(text string, attrs templ.Attributes) {
    <button class="rounded w-20 text-center p-2 bg-p-color" { attrs... }>{ text }</button>
}
// usage
@Button("login", templ.Attributes{ "hx-post": "/login"})

As you can see, it will work like this, but LSP kind of fails here, as the autocomplete of HTMX will not work with templ.Attributes. Now, this may not be case for every IDE, I will mention mine - neovim with HTMX LSP configured for templ files and installed using lsp-zero.

Now, if I let go of my idea of reusability = reusable UI components. I can achieve the same with just CSS and use HTMX as a tool. But there I have to let go of tailwind CSS, as remembering all utility classes of a primary Button is a pain.

var primaryColor := "red"
css primaryButton() {
   border-radius: 5px;
   width: 30px;
   padding: 2px;
   background-color: { primaryColor }
}

// then no need for button component, I can just use
templ Home() {
 <button class={ primaryButton() } hx-post="/login">Login</Button>
}

Not sure if this approach defeats the purpose of components and I may not using full potential templ library.

Now my question to the experts here, how would you guys do this?
I am aware this can be a LSP issue, coz if HTMX lsp starts working with templ.Attributes everything falls into place.

@peterszarvas94
Copy link

peterszarvas94 commented Jan 10, 2024

I am not an expert, but I would do:

// the component
package components;

templ Button(classes string) {
  <button
    hx-post="/login"
    class={ "rounded-[5px] w-[30px] p-[2px] " + classes }
  >
    Login
  </button>
}

// usage in other templ file
@components.Button("bg-[#ff0000]")

Or you can do more "typesafe" things like:

// the component
package components;

type variant string

const (
  Red   variant
  Green variant
)

func (v variant) String() string {
  switch v {
  case Red:
    return "bg-[#ff0000]"
  case Green:
    return "bg-[#00ff00]"
  default:
    return ""
  }
}

templ Button(variant variant) {
  <button
    hx-post="/login"
    class={ "rounded-[5px] w-[30px] p-[2px] " + variant.String() }
  >
    Login
  </button>
}

// usage in other templ file
@components.Button(components.Red)

Both LSP works if set up correctly.

@neuronishad
Copy link
Author

@peterszarvas94 But won't every button make a post call to login ?

@a-h
Copy link
Owner

a-h commented Jan 16, 2024

I'm glad you're thinking about this! It's one of the things I had in mind with the design of templ - with templ components just being functions that can be exported, and having built-in CSS.

I had a bit of a chat with @msonawane about it here: #311 (comment)

Maybe you might join forces if you're interested in building out a re-usable set of components for public use!

@neuronishad
Copy link
Author

@a-h I would love to look into this. I have started a discussion for some doubts I have.

@msonawane Let me know if you are still working on the same.

Closing the issue, as it was never one :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants