This article covers creating a Riot Radio 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/
A Radio is often part of a group of Radio buttons: Only one radio button in a given group can be selected simultaneously (see the following screenshot). The goal is to create a Radio component with BeerCSS design and listen to change events.
Note: The article doesn't cover how to create a radio as an Icon or as an Image.
Radio Component Base
First, create a new file named c-radio.riot
under the components folder. The c-
stands for "component", a useful naming convention and a good practice.
Write the following HTML code (found on the BeerCSS documentation) in ./components/c-radio.riot
:
<c-radio >
<label class="radio">
<input type="radio" name={ props?.name } value={ props?.defaultValue } checked={ props?.defaultValue === props?.value } disabled={ props?.disabled }>
<span>
<slot></slot>
</span>
</label>
</c-radio>
Let's break down the code:
- The
<c-radio>
and</c-radio>
defined a custom root tag, with the same name as the file. You must write it; otherwise, it may create unexpected results. Using the<label>
as a root tag or redefining native HTML tags is a bad practice, so startingc-
is a good naming. - A name attribute is required for each Radio: Radios of the same group must have the same name.
- The radio takes two different values attributes:
- The default-value attribute defines the radio value.
- the value attribute defines the value of the group.
- To enable the
checked
attribute, the value of the group must be equal to the radio default value default-value. - A radio can have a label; it must be passed as a Slot, a Riot tag to inject HTML templates in a child component from its parent.
- The element is disabled if the
props.disabled
attribute exists and the value istrue
.
Now to create a radio group, let's create a parent component named ./components/c-radio-group.riot. The following HTML was copied from the BeerCSS documentation, and RiotJS logic was added:
<c-radio-group class="field middle-align">
<nav>
<slot></slot>
</nav>
<span class="helper" if={ props?.helper && !props?.error }>{ props.helper} </span>
<span class="error" if={ props?.error }>{ props.error}</span>
</c-radio-group>
- To define multiple Radio components in the group, Radios are injected thanks to the
<slot></slot>
tag: The Slot tag is a special Riot.js core feature that allows you to inject and compile the content of any custom component. - The helper span is displayed if the helper attribute exists.
- If the error attribute exists, the error span is displayed and the helper is hidden.
Finally, load and instantiate the c-radio.riot and c-radio-group.riot, in a front page named index.riot:
<index-riot>
<div style="width:600px;padding:20px;">
<h4 style="margin-bottom:20px">Riot + BeerCSS</h4>
<c-radio-group oninput={ changed }>
<c-radio default-value="blue" value={ state.value } name="color">Blue</c-radio>
<c-radio default-value="red" value={ state.value } name="color">Red</c-radio>
<c-radio default-value="green" value={ state.value } onclick={ clicked } name="color">Green</c-radio>
</c-radio-group>
Selected: { state.value }
</div>
<script>
import cRadio from "./components/c-radio.riot";
import cRadioGroup from "./components/c-radio-group.riot"
export default {
components: {
cRadio,
cRadioGroup
},
state: {
value: "green"
},
changed (ev) {
this.update({ value: ev.target.value })
}
}
</script>
</index-riot>
Code details:
- Components are imported with
import cRadio from "./components/c-radio.riot";
andimport cRadioGroup from "./components/c-radio-group.riot"
then loaded in the components:{} Riot object. - The component RadioGroup is instantiated with
<c-radio-group></c-radio-group>
on the HTML. - The component Radio is instantiated within the Radio group as a Slot, such as:
<c-radio-group><c-radio>label<c-radio></c-radio-group>
. - Each Radio gets the same group name: color.
- Each Radio gets a default value with the attributes name default-value: red, green or blue.
- The state of the radio group is stored in the state Riot object
state: { value: 'green' }
. Green is the default value. - If a click is made on the Radio group, the
change
event is fired, and thechanged
function is executed to update the value of the group state.value. - To update a state, you must use the update() Riot function, such as:
this.update({ value: ev.target.value })
. The state.value gets the Radio change event value.
Here is the generated HTML:
Radio Component Testing
It exists two methods for testing the Radio component, and it is covered in two different articles:
Conclusion
Voilà 🎉 We created a Radio Riot Component using Material Design elements with BeerCSS.
The source code of the radio is available on Github:
https://github.com/steevepay/riot-beercss/blob/main/components/c-radio.riot
Feel free to comment if you have questions or need help about RiotJS.
Have a great day! Cheers 🍻