bloom
My Team Lead Chris approached me with his latest side project - Bloom. A component library for Elixir and Liveview which is written in the style of ShadCN.
Components which you install and vendor in your project.
Having worked extensively in the design system and component library at Multiverse, Stardust, I was excited to see what Chris had been working on.
Current state of affairs
The library is currently pretty bare bones. A handful of components have been implemented, and a Phoenix Storybook has been deployed to showcase them.
Trying something different
When I started thinking about how I could contribute to Bloom, I realised that I wanted to try something different. Although there are many components which are in need of implementation, I want to see if there is some bespoke functionality I could add, which no other component library has.
Audio components
Audio is underused on the web.
There are great APIs built into the browser for Javascript to interact with the user’s machine, but I so rarely find them used across the web.
This path led me to 2 potential components to start with
- Microphone input Some component which will let the user record their machine’s microphone and either stream live to the backend, or save the recording and upload as a base64 encoded file.
- Sound effect player A component which will let the backend trigger sound effects on the frontend. This could be used for notifications etc.
I talked with Chris about these components and he was incredibly excited by the idea. There is just one problem…
Lack of Javascript
At the moment every component is pure Elixir liveview code. There is no Javascript in the project at all.
Liveview has a reasonably good story around adding custom functionality via the JS hooks API, but these hooks need to be added to the frontend Socket on first render of a liveview app.
So before I can dig into the actual components, I need to POC the Javascript integration.
My first contribution
I spent an evening digging into how best to approach the JS interop piece of the project.
The constraints were:
- Keep the JS as minimal as possible
- No build step
- Only install the JS for the specific component being installed
In the end it boiled down to adding some JS in the conventional assets/js
folder, and then moving them alongside the compiled Elixir templates in priv/templates
.
Pretty simple. But simple is good!
Here’s the PR. The 4th pull request on the project!
Testing the PR
I didn’t want to include the test files in the PR, so I raised a separate draft PR which included an “alert” component, which literally just fires a JS alert()
when the component is mounted.