teamon
headless - Headless (unstyled) UI components for Phoenix (with Alpine)
After spending some time recently researching various ways of building modern UIs I came to one sad conclusion: if one wants to build a modern interactive application in Phoenix (+ LiveView) there are not many choices of complex components, like for example a dropdown with search. Incorporating existing solutions requires data manipulation that are not easy to keep track of especially in LiveView context.
That’s how headless was born - a collection of unstyled, UI components for Phoenix and Phoenix LiveView.
https://github.com/teamon/headless
Goals & Rules
-
Provide unstyled Phoenix components as building blocks for your own UI components
-
If something can be achieved with HTML and CSS only, it should be done with HTML and CSS only (no-JS)
-
Where JS is required, use Alpine.js
-
Use
Alpine.data()instead of inline markup -
Components must work with standard Phoenix controllers (dead views)
-
Components must work with Phoenix LiveView
-
Components must work with standard Phoenix forms
-
Components must be accessible (aria attributes, keyboard navigation, focus, etc.)
Non-goals
Providing 100+ HTML components - headless should focus only on tricky components that are non-trivial to implement correctly, something like Headless UI for React and Vue.
Future goals
In the perfect world there would be a collection of headless components and then some UI libraries built on top of that providing elegant styling.
Status
Very very early, Proof of Concept stage.
So far I did an example <.toggle> component that uses a checkbox under the hood and my nemesis <.combobox/> that tried to leverage all the things that we get with Phoenix & LiveView and provide a good client-side experience on top of that.
I would love to hear any feedback on the idea itself, the implementation, etc.
Most Liked
sodapopcan
It’s good to see more effort in this space! Are you aware of Doggo? It’s already quite far along though still a work in progress. A lot of the more complex JS has not been implemented yet. This is not my project so I can’t speak to plans there but I am using it in a personal project and currently converting a production app over to it.
For myself, the Alpine dependency makes Headless a non-starter. I’m not recommending you don’t use it, but I feel JS commands+hooks are a better route in terms of longevity within the ecosystem. Using Alpine isn’t a bad thing per se as lots of Phoenix-folks still use it, but you’re boxing out the dependency-conscious among us… which is also not necessarily a bad thing per se as it’s providing some variety. Good work, overall!
greven
To add to what @sodapopcan said, great initiative, we need more in the community! But I agree with the Alpine sentiment. I really like Alpine but it has a big drawback for me is the CSP limitation: CSP — Alpine.js
I rather deal hooks that having problems and workaround the CSP. Even though as a library AlpineJS is pretty nice regarding DX. ![]()
teamon
After researching more into ways of bulding a headless library I decided to go with “api-only” approach like Sprout UI did.
And there’s a demo website now: https://headless.fly.dev
Popular in Announcing
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance








