This article covers creating a Riot Chip component, using the Material Design CSS BeerCSS. Before starting, make sure you have a base application running, or read my previous article Setup Riot + BeerCSS + Vite.
These articles form a series focusing on RiotJS paired with BeerCSS, designed to guide you through creating components and mastering best practices for building production-ready applications. I assume you have a foundational understanding of Riot; however, feel free to refer to the documentation if needed: https://riot.js.org/documentation/
Chips help people enter information, make selections, filter content, or trigger actions (see the following screenshot). The goal is to create a Chip Riot component that supports all styling and listens to click events.
Chip Component Base
First, create a new file named c-chip.riot under the components folder. The c-
stands for "component", a useful naming convention and a good practice.
Into ./components/c-chip.riot, write the following HTML (found in the BeerCSS documentation):
<c-chip>
<a class="
chip
{props?.small ? 'small' : null }
{props?.medium ? 'medium' : null }
{props?.large ? 'large' : null }
{props?.smallElevate ? 'small-elevate' : null}
{props?.mediumElevate ? 'medium-elevate' : null}
{props?.largeElevate ? 'large-elevate' : null}
{props?.round ? 'round' : null }
{props?.fill ? 'fill' : null }
{props?.vertical ? 'vertical' : null }
">
<i if={ props?.icon }>{ props.icon }</i>
<img class={props?.inline ? null : "responsive" } if={ props?.img } src={ props.img }>
<span><slot></slot></span>
<i if={ props?.iconend }>{ props.iconend }</i>
</a>
</c-chip>
Let's break down the code:
- The
<c-chip>
and</c-chip>
defined a custom root tag, with the same name as the file. You must write it; otherwise, it may create unexpected results. Using the<a>
as a root tag or redefining native HTML tags is a bad practice, so startingc-
is a good naming. - Using the
<slot>
tag you can inject custom HTML templates in a child component from its parent: we will inject the chip's label. - A chip has many variations classes: size, elevation and form (round, fill or vertical). It is injected conditionally if the corresponding props exist. For instance, if the property
props.round
exists, it will enable theround
class in the component. - Two icons can be passed at two positions: either as a prefix or as a suffix of the label:
- the property
icon
injects the glyph before the label - the property
iconend
injects the glyph after the label
- the property
- Thanks to the
img
property, an image can be injected instead of an icon.
Finally, the c-chip.riot can be instantiated into a front page index.riot. Here are all Chip variations, either filled, rounded, including an image or icon:
<index-riot>
<div style="width:800px;padding:20px;">
<h4 style="margin-bottom:20px;margin-left:10px;">Riot + BeerCSS</h4>
<h6 style="margin-left:10px">Chip Variations</h6><br>
<c-chip>Suggestion</c-chip>
<c-chip iconend="close">Input</c-chip>
<c-chip icon="check">filter</c-chip>
<c-chip icon="today">assist</c-chip>
<c-chip img="./favicon.png" inline="true">image</c-chip>
<c-chip img="./favicon.png">image</c-chip>
<br><br>
<c-chip round="true">Suggestion</c-chip>
<c-chip round="true" iconend="close">Input</c-chip>
<c-chip round="true" icon="check">filter</c-chip>
<c-chip round="true" icon="today">assist</c-chip>
<c-chip round="true" img="./favicon.png" inline="true">image</c-chip>
<c-chip round="true" img="./favicon.png">image</c-chip>
<br><br>
<c-chip fill="true">Suggestion</c-chip>
<c-chip fill="true" iconend="close">Input</c-chip>
<c-chip fill="true" icon="check">filter</c-chip>
<c-chip fill="true" icon="today">assist</c-chip>
<c-chip fill="true" img="./favicon.png" inline="true">image</c-chip>
<c-chip fill="true" img="./favicon.png">image</c-chip><br><br>
<c-chip fill="true" round="true">Suggestion</c-chip>
<c-chip fill="true" round="true" iconend="close">Input</c-chip>
<c-chip fill="true" round="true" icon="check">filter</c-chip>
<c-chip fill="true" round="true" icon="today">assist</c-chip>
<c-chip fill="true" round="true" img="./favicon.png" inline="true">image</c-chip>
<c-chip fill="true" round="true" img="./favicon.png">image</c-chip>
</div>
<script>
import cChip from "./components/c-chip.riot"
export default {
components: {
cChip
},
}
</script>
</index-riot>
Code break-down:
- The component is imported with
import cChip from "./components/c-chip.riot";
then loaded into the components:{} Riot object. - On the HTML, the Chip component is instantiated with
<c-chip>label<c-chip>
- Pass attributes to the tag to enable variations, for instance:
<c-chip fill="true" round="true" icon="check">filter</c-chip>
.
Screenshot of the generated HTML:
Chip Component Events
As mentioned, a chip is used to filter, suggest and trigger actions. A real-world example would be that you must select your flat's amenities for a rental application.
Let's make a group of chips for each amenity and check if it is selected.
Here is the corresponding HTML and Riot code in the index.riot:
<index-riot>
<div style="width:800px;padding:20px;">
<h6 style="margin-left:10px">Amenities</h6><br>
<c-chip each={ el in state.amenities } onclick={ (ev) => clicked(el.label) } fill={ el.checked === true } icon={ el.checked === true ? 'check' : null }> { el.label } </c-chip>
</div>
<script>
import cChip from "./components/c-chip.riot"
export default {
components: {
cChip
},
state: {
amenities: [
{ label: "Wash / Dryer", checked: false },
{ label: "Ramp Access", checked: false },
{ label: "Garden", checked: false },
{ label: "Cat OK", checked: false }
]
},
clicked (label) {
const _el = this.state.amenities.find(el => el.label === label);
if (_el) {
_el.checked = !_el.checked;
this.update();
}
}
}
</script>
</index-riot>
Code details:
- A list of Chips is printed thanks to the Each Riot attribute.
- Each chip is listening to a click event with
onclick={ (ev) => clicked(el.label) }
. If a click event is fired, the functionclicked
is executed, and the label is passed as first argument. - The
clicked
function finds the list item based on the label, then thechecked
property is updated. - When the
checked
is true, two attributes are enabled fill and icon.
Chip Component Testing
It exists two methods for testing the Chip component, and it is covered in two different articles:
Conclusion
Voilà 🎉 We created a Chip Riot Component using Material Design elements with BeerCSS.
The source code of the chip is available on Github:
https://github.com/steevepay/riot-beercss/blob/main/components/c-chip.riot
Feel free to comment if you have questions or need help about RiotJS.
Have a great day! Cheers 🍻