A library to build generic HTML components

Hi everyone,

One of the issues I’ve consistently come across is writing consistent HTML components. I got the idea to write a component generation library with the premise of allowing you to build reusable components and help standardise your components across different projects or parts of the same project.

For example:

defcomp :alert, type: {:content_tag, :div}, variants: [:primary, :success], class: "alert"

Would generate the following functions for you (including block syntax):

      alert "Alert!"
      #=> <div class="alert">Alert!</div>      

      alert :primary, "Alert!"
      #=> <div class="alert alert-primary">Alert!</div>

      alert :success, "Alert!"
      #=> <div class="alert alert-success">Alert!</div>

      alert :success, "Alert!", class: "extra"
      #=> <div class="alert alert-success extra">Alert!</div>

Although the component in this example happens to be Bootstrap, the library doesn’t really care. But it does make building your own library of components easy. For example, it’s possible to build a good portion of Bootstrap’s components using the current version. You can also use it to generate components for most HTML templates.

There are other features like delegating rendering to other libraries (useful for Phoenix.HTML.Link), composable components with :parent, :append, and :prepend options, as well as a few other goodies.

    defcomp :close_button, type: {:content_tag, :button}, class: "close", data: [dismiss: "alert"], aria: [label: "Close"]
    defcomp :alert, type: {:content_tag, :div}, class: "alert", prepend: {&close_button/2, "&nbsp;"}, variants: [:primary]

    alert :primary do
    #=> <div class="alert alert-primary">
    #    <button aria-label=\"Close\" class=\"close\" data-dismiss=\"alert\">
    #      <span>&times;</span>
    #    </button>
    #    Content
    #   </div>

There is some documentation and decent test coverage.

Before I release it, any feedback or critique as far as approach or usefulness is greatly appreciated.