This content originally appeared on DEV Community and was authored by Mads Stoumann
We're all familiar with dev.to's “Reaction Component” (although I'm still not sure, what the unicorn is for!) Here's a short tutorial on how to create a “Reaction Component” – both with and without JavaScipt.
Let's start with the CSS version!
Markup
We're going to wrap each reaction in a <label>
, and add the <svg>
and an empty <span>
after a <input type="checkbox">
:
<label aria-label="React with heart">
<input type="checkbox" name="reaction-heart" value="75" style="--c:75" />
<svg></svg>
<span></span>
</label>
The <input type="checkbox">
is what we'll use to control both state
and value
.
Icon
On dev.to, two different icons are used, when you “react” to something. For the “like“-action, there's an unfilled heart and a filled heart. Same story for the “unicorn” and “bookmark”-reactions.
One could argue, that with slight design changes, the icons could simply toggle SVG's fill
, stroke
or stroke-width
– but let's leave it at two icons. We'll <g>
roup them within a single SVG:
<svg viewBox="0 0 24 24">
<g><path d="M21.179 12.794l.013.014L12 22l-9.192-9.192.013-.014A6.5 6.5 0 0112 3.64a6.5 6.5 0 019.179 9.154zM4.575 5.383a4.5 4.5 0 000 6.364L12 19.172l7.425-7.425a4.5 4.5 0 10-6.364-6.364L8.818 9.626 7.404 8.21l3.162-3.162a4.5 4.5 0 00-5.99.334l-.001.001z"></path></g>
<g><path d="M2.821 12.794a6.5 6.5 0 017.413-10.24h-.002L5.99 6.798l1.414 1.414 4.242-4.242a6.5 6.5 0 019.193 9.192L12 22l-9.192-9.192.013-.014z"></path></g>
</svg>
In CSS, we an use the :checked
pseudo-selector to toggle between the two icons (in <g>
-tags):
[name*="reaction-"]:checked + svg g:first-of-type,
[name*="reaction-"]:not(:checked) + svg g:last-of-type {
opacity: 0;
}
[name*="reaction-"]:checked + svg g:last-of-type {
opacity: 1;
}
Cool, now we can toggle between the two icons using the checkbox, let's add a counter! Did you notice the style="--c:75"
in the markup?
We'll use that for a CSS counter:
counter-reset: reaction var(--c);
Unfortunately, we can't use the value
-attribute, as in:
counter-reset: reaction attr(value);
– so we have to use that extra custom property, --c
, for the initial value.
Then, we'll hook into the :checked
-selector again:
[name*="reaction-"]:checked {
counter-increment: reaction;
}
And that empty <span>
in the markup will now play it's part:
span::after {
content: counter(reaction);
}
But why the empty <span>
? That's because we have to add the counter as pseudo-element content (::before
or ::after
).
Unfortunately, we can't add a pseudo-element to the <input type="checkbox">
, as <input>
-tags are part of the group of tags, that can't have children (aka “self-closing” tags) or pseudo-content (actually they can in Chrome and Safari, but it's not part of the spec!).
The rest is just bits of styling. Here's the CSS-only example on Codepen:
JavaScript
Even though the CSS-only version is cool, it's not very practical. You'll probably want to store the reaction somewhere!
Let's remove the counter-related stuff from the CSS, and the style="--c"
-part from the markup. We'll wrap the reactions in a <form id="react">
, and listen for changes using the onchange
-eventListener:
react.addEventListener('change', (e) => {
const t = e.target;
t.parentNode.lastElementChild.innerText = t.value = t.value - 0 + (t.checked ? 1 : -1);
});
This small snippet will add or subtract 1
(one) from the value
of the current reaction, then set the innerText
of the <span>
to that.
It's within this snippet, you can add a fetch()
(with POST
) to store the current reaction.
On dev.to, for instance, a small JSON
-object is POST
ed:
{
result: "create",
category: "like"
}
Example, using JavaScript:
If you want to set the text of all the <span>
-elements to the value
of the <input>
s, use this small snippet to iterate the elements
-collection of the <form>
:
[...react.elements].forEach(t => t.parentNode.lastElementChild.innerText = t.value);
That's it! Recently, there was a “Star Rating”-challenge here on dev.to (my entries were Star Rating Using a Single Input and Mood Selector).
It's always interesting to see how other developers solve problems, so please share a link in the comments, if you modify my example, or – event better – make your own “Reaction Component”!
This content originally appeared on DEV Community and was authored by Mads Stoumann
Mads Stoumann | Sciencx (2021-07-17T08:24:00+00:00) Building a Reaction Component. Retrieved from https://www.scien.cx/2021/07/17/building-a-reaction-component/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.