Flexible UI components
At carwow we have a styleguide. It’s a great way to keep a more consistent design and it also helps to improve designer and developer communication as it creates a common vocabulary for UI discussions.
That’s the place we keep shared components that act as building blocks which can be combined to create the things you see on our website. And in order to make it easier to “componentise” the design as much as we can, we’ve created the concept of UI components.
An UI component is simply a partial describing how certain design elements are rendered. It accepts a hash of custom properties and a block containing a Haml snippet that’s usually appended to the component but can be also used in a different location within the component.
If you need a tooltip, for example, we would use the following code:
The snippet above would be rendered as the following:
It works quite well but lacks flexibility. We can’t, for example, have properties that are composed by other components once we can only provide one block to it. Also, for the content, it’s not ideal to write HTML in the properties. Especially because everything else is written in HAML.
In my opinion, it would be great to have a way to describe a component using a simple DSL (like rails
JBuilder, for example). Something like:
While you can still set the properties hash like the
position, it would also allow us to describe properties as blocks. In this case, the
placeholder blocks behave like component custom properties.
It would be awesome if we also could create composed components. A component the contains other components. Something like:
ui_icon behaves like an
Cool! With this draft in mind I decided to give it a try and, to my surprise, it turned out to be a super easy change.
I created the
ComponentProperties class that can catch the properties described for the blocks with the help of the (in)famous
method_missing is the one to pay attention here. It catches the property name and the block that defines it and, using capture, sets the rendered view to the hash. To be able to do the that I’ve included the Haml helpers so I could get advantage of
capture_haml that basically renders the haml code provided in the property block.
ui_component helper method we have the following:
If a block is given we initialise a component then yield it to the block to capture and store the custom properties.
The component partial (located in the
/views/components folder) reads like so:
All properties set in the hash or through the blocks can be accessed from the
properties hash assigned to the partial.
Here’s an example of the new way of setting the component properties:
That will generate the following html snippet:
Where the SVG content is the result of our
ui_component now can handle blocks for all its properties. This allow us, for example, to create components that contain other components.
It’s a simple change but it brings a lot of power and flexibility to our ui components.
Especially now that we’re planning to play with Atomic Design it could be very handy.