This article covers creating a Riot Icon 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/
There are three types of icons on BeerCSS: default using Google Material Glyphs, SVG, or as an image (see following screenshot). The goal is to create an icon Riot component that supports all three formats and listens to click events.
Icon Component Base
First, create a new file named c-icon.riot under the components folder. The c-
stands for "component", a useful naming convention and a good practice.
Into ./components/c-icon.riot, write the following HTML (found on the BeerCSS documentation):
<c-icon>
<i class="
{ props?.tiny ? ' tiny' : null}
{ props?.small ? ' small' : null}
{ props?.large ? ' large' : null}
{ props?.extra ? ' extra' : null}
{ props?.fill ? ' fill' : null}
{ props?.primary ? ' primary-text' : null}
{ props?.secondary ? ' secondary-text' : null}
{ props?.tertiary ? ' tertiary-text' : null}
">
<slot></slot>
</i>
</c-icon>
Let's break down the code:
- The
<c-icon>
and</c-icon>
defined a custom root tag, with the same name as the file. You must write it; otherwise, it may create unexpected results. Using the 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: Now we can inject either a string (for Google Material Icon), an SVG tag, or an image tag. - A BeerCSS icon supports different sizes and theme classes: Each class is applied conditionally if the corresponding props exists. Properties are defined on the HTML attribute name.
Finally, the c-icon.riot can be instantiated into a front page index.riot:
<index-riot>
<div style="width:600px;padding:20px;">
<h4 style="margin-bottom:20px">Riot + BeerCSS</h4>
<c-icon>check_circle</c-icon>
<c-icon large="true">
<svg viewBox="0 0 24 24">
<path d="M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M7.07,18.28C7.5,17.38 10.12,16.5 12,16.5C13.88,16.5 16.5,17.38 16.93,18.28C15.57,19.36 13.86,20 12,20C10.14,20 8.43,19.36 7.07,18.28M18.36,16.83C16.93,15.09 13.46,14.5 12,14.5C10.54,14.5 7.07,15.09 5.64,16.83C4.62,15.5 4,13.82 4,12C4,7.59 7.59,4 12,4C16.41,4 20,7.59 20,12C20,13.82 19.38,15.5 18.36,16.83M12,6C10.06,6 8.5,7.56 8.5,9.5C8.5,11.44 10.06,13 12,13C13.94,13 15.5,11.44 15.5,9.5C15.5,7.56 13.94,6 12,6M12,11A1.5,1.5 0 0,1 10.5,9.5A1.5,1.5 0 0,1 12,8A1.5,1.5 0 0,1 13.5,9.5A1.5,1.5 0 0,1 12,11Z"></path>
</svg>
</c-icon>
<c-icon extra="true">
<img src="/favicon.png">
</c-icon>
</div>
<script>
import cIcon from "./components/c-icon.riot";
export default {
components: {
cIcon
}
}
</script>
</index-riot>
Code break-down:
- The component is imported with
import cIcon from "./components/c-icon.riot";
then loaded into the components:{} Riot object. - On the HTML, the Icon component is instantiated with
<c-icon>icon_name<c-icon>
- Since the component uses a slot, different types of icons can be passed: as an SVG or as an image.
- If the icon is coming from Google Material Fonts, and if the icon name has a space character in it, replace each space with an underscore. For instance, if the name on Google Font is "Chevron Right", you must write on the slot:
chevron_right
.
Screenshot of the generated HTML:
To apply different icon sizes and themes, pass the following attributes to the component tag definition: tiny
, small
, large
, extra
, primary
, secondary
, tertiary
, or fill
, such as:
<c-icon tiny="true">check_circle</c-icon>
<c-icon small="true">check_circle</c-icon>
<c-icon>check_circle</c-icon>
<c-icon large="true">check_circle</c-icon>
<c-icon extra="true">check_circle</c-icon>
<c-icon extra="true" fill="true">check_circle</c-icon>
<c-icon extra="true" fill="true" primary="true">check_circle</c-icon>
<c-icon extra="true" fill="true" secondary="true">check_circle</c-icon>
<c-icon extra="true" fill="true" tertiary="true">check_circle</c-icon>
The generated HTML of icon variations:
Icon Component Testing
It exists two methods for testing the Icon component, and it is covered in two different articles:
Conclusion
Voilà 🎉 We created an Icon Riot Component using Material Design elements with BeerCSS.
The source code of the icon is available on Github:
https://github.com/steevepay/riot-beercss/blob/main/components/c-icon.riot
Feel free to comment if you have questions or need help about RiotJS.
Have a great day! Cheers 🍻