DEV Community

Cover image for Building a Reaction Component

Building a Reaction Component

Mads Stoumann on July 17, 2021

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 cre...
Collapse
 
grahamthedev profile image
GrahamTheDev • Edited

Oh you want to start the next war? I didn't think the last one had truly ended.

I don't remember signing the peace treaty on that one and Temani decided to fire another shot so I am just gathering my "forces" (pun intended)! 😉😋🤣

Few things (yes you know what I am like):-

  1. iPhone - the box-shadow animation is buggy so your surrounding circle flickers when it transitions. Pretty sure it is an easy fix but cant spot it on my phone.

  2. It isn't accessible. Your <label> will either say "React With Heart" (if you include the aria-label you showed in the first code snippet...you didn't add it to any codepens) and not read the value inside the <label>, or it will just read the value inside the <label> (which is not useful as it will literally read "75").

Also when you increment your counter the number will not change for screen readers in your CSS only version so I don't think you could ever make that accessible without some hacks!

It would also be a good idea to add aria-hidden to the SVGs just for robustness (as some older screen reader / browser combos will attempt to tell the screen reader that there is an SVG there). If you really want to cover all the bases also add focusable="false" due to some ancient browsers making inline SVGs focusable!

Obviously it still gets my ❤ and 🦄 as always, just thought I would point them out!

Now I am going to look at how DEV implemented it and see what issues they have when I get back to my PC 😉

Collapse
 
afif profile image
Temani Afif

Should I prepare the guns??

Collapse
 
grahamthedev profile image
GrahamTheDev • Edited

You picked the wrong Gif from that film! 🤣🤣

Endhiran film - ball of guns scene

Oh and "Endhiran" is a film on my watch list if I can find an English Dub due to the insane clips I have seen, just looks beyond silly! It is Matrix, iRobot, Terminator, Transformers, Alita and Austin Powers in one movie 🤣

Thread Thread
 
madsstoumann profile image
Mads Stoumann

Never heard about that movie!
BTW: I was once in a Bollywood-movie! Spent a whole day “playing” a guy in the audience in a cinema in the movie “Na Tum Jaano Na Hum". I later bought it on DVD, but couldn't find the scene! 😂😂😂

Thread Thread
 
grahamthedev profile image
GrahamTheDev

Ok so now I have a new mission far more important than winning a war, find Mads on a film!

I will have to get the Blu-ray version so the definition is high enough to spot you! 🤣

That is one of those great little factoids to pull out of your back pocket, how on Earth did you manage that one?

Thread Thread
 
madsstoumann profile image
Mads Stoumann

I was backpacking with a friend in India, when a guy approached us in a café. He needed some “white dudes” to sit in the audience of a cinema, just behind the main characters. There wasn't any movie playing, so to simulate the “flicker”, a guy was waving two baseball bats in front of a large lamp! 😂

Thread Thread
 
grahamthedev profile image
GrahamTheDev

Absolutely brilliant! That image in my head is hilarious 🤣🤣

Thread Thread
 
siddharthshyniben profile image
Siddharth

By the way you should definitely watch "Endhiran", I've watched it and it's a cool movie

Thread Thread
 
madsstoumann profile image
Mads Stoumann

I will! 😁

Collapse
 
madsstoumann profile image
Mads Stoumann

Yes, please go ahead and make that unicorn-icon with a single <div> and CSS ;-)

Thread Thread
 
madsstoumann profile image
Mads Stoumann

I can make the heart and bookmark in CSS ... but the unicorn?! 😭

Collapse
 
madsstoumann profile image
Mads Stoumann • Edited

Thanks, great feedback as always!

  1. I guess it's the -webkit-tap-highlight-color: transparent;, which were missing, not box-shadow.
  2. I know, I didn't spend time to a11y-fixes this time - it was more a “How much is possible with only CSS”-challenge, and the CSS-only will never be accessible, obviously! ;-) But I guess an aria-label="Total reactions 75" on the span, and pointer-events:none and aria-hidden on the SVG would be enough? But ... if the reactions are “live”, I guess even more araia-stuff is required for feedback.
Collapse
 
grahamthedev profile image
GrahamTheDev

It’s an Interesting one for the label as it serves two purposes, it tells you what the control is for (“like this article”) and at the same time current likes (“this article has 75 likes” and that number changes if you like it). So you have to find a good way of combining the two.

If you got that right with some careful phrasing you wouldn’t need any aria attributes.

As for CSS being accessible the content property can now take alt text...it just doesn’t have good support yet!

So you can do content: * / “required” and the “required” part is what a screen reader will hear! So in the future it might actually be possible!

Thread Thread
 
madsstoumann profile image
Mads Stoumann

It's a bit tricky! You have the “total amount of likes” in the value, but want the label to announce “React with ...”! Interesting about the content-attribute, didn't know that – I always love it, when something is or will be solvable without JavaScript (I have nothing against JavaScript, but only use it when necessary)

Thread Thread
 
grahamthedev profile image
GrahamTheDev

Yup, that is one of the "soft skills" of accessibility, label names and alt text is as much art as science.

My gut reaction is:

"React with a unicorn to this article? 75 others have given it a unicorn".

That way when you do check your checkbox that makes sense and at the same time you don't have to worry about incrementing the number as it still makes sense.

It would be one of those things I ponder as I work and come up with better phrasing, but the key to any answer would be "other people's reactions" as it eliminates the need to increment and report back.

Glad I managed to teach you something as it has been seeming like a one way street lately (you teaching me!) 😋🤣🤣

Thread Thread
 
madsstoumann profile image
Mads Stoumann

"React with a unicorn to this article? 75 others have given it a unicorn".

This is brilliant, precise and clear!

I’m always learning from your articles as well! dev.to has great content, when you ignore the Top 10 and listicles 😁

Thread Thread
 
link2twenty profile image
Andrew Bone

I'm gonna do a "top 10 @inhuofficial posts" post \s

Thread Thread
 
grahamthedev profile image
GrahamTheDev • Edited

Oh you do like to make me love and hate your comments at the same time lately...glad you get me 😜🤣

Anyway if you actually liked and read my posts you would know it has to be a prime number so it should be 11 at least! 😂🙈 go reread my guide to listicles as punishment for causing me pain again!

Collapse
 
lexlohr profile image
Alex Lohr

Instead of aria-hidden, I would prefer role="presentation", which is for that exact use case.

Collapse
 
grahamthedev profile image
GrahamTheDev

aria-hidden removes it from the accessibility tree entirely, role="presentation" purely removes roles from an item to give it no semantic meaning.

To be fair here it probably doesn't matter as either way and support is pretty similar for both attributes so this is one of those very rare "personal preference" instances I suppose, both would be accessible.

Thread Thread
 
lexlohr profile image
Alex Lohr

I prefer role="presentation", because it conveys more semantic meaning than "hide it from assistive technology".

Thread Thread
 
grahamthedev profile image
GrahamTheDev

It is semantically incorrect to use role="presentation" here.

The icon has meaning, it isn't accompanied by a visible label.

role="presentation" is not really designed for this scenario, it is designed for either:

  • removing semantic meaning from an element (back in the days when tables were used for layout for example)
  • marking a graphic or image as decorative (background images).

Neither of the above are true.

Where role="presentation" is applicable is if you have a button with text and an icon, the icon adds nothing of value so it is presentational. That is not the case here as the icon is the label.

The most semantically correct way of creating this control would be to use the <title> and or <description> on the SVG as the label information (and using aria-labelledby etc. to ensure it is as robust as possible.

When the icon is the sole source of information you either have to give it alt attributes (or <title> which is the equivalent in SVG) or hide it entirely and replace it with a label for screen readers that makes sense.

At the end of the day, both options will work, but if we really want to be semantically correct the following is the proper way of doing it:

<label>
    <input type="checkbox" name="reaction-heart" value="75" style="--c:75" />
    <svg role="image" aria-labelledby="unicorn-title" viewBox="0 0 24 24">
         <title id="unicorn-title">React with a unicorn to this article? 75 others have given it a unicorn</title>
         [...]
    </svg>
    <span aria-hidden="true">75</span>
  </label>
  <label>
Enter fullscreen mode Exit fullscreen mode

That is the best option from a semantics perspective.

Now in the scenario I suggested we instead decided to create a label just for screen readers. In that scenario it is entirely correct to use aria-hidden as we want to remove the item we are replacing from the accessibility tree.

As I said, both options work so we are splitting hairs here, but it certainly isn't semantically correct to mark an item as presentational if it is the source of information.

Collapse
 
lexlohr profile image
Alex Lohr

You don't need to use a counter. CSS knows content: attr(…) for quite some time, see developer.mozilla.org/en-US/docs/W....

Collapse
 
madsstoumann profile image
Mads Stoumann • Edited

Yes, but as I write in the article, it doesn't work with attr(value), unfortunately :-(
Or do you mean some other way?

Collapse
 
lexlohr profile image
Alex Lohr

You can use an additional data attribute.

Thread Thread
 
madsstoumann profile image
Mads Stoumann • Edited

How would you do the CSS-only version without a counter (adding or subtracting 1)?

Thread Thread
 
lexlohr profile image
Alex Lohr

Can't you initialize the counter from an attr()? Then at least you wouldn't have to abuse style for content.

Thread Thread
 
lexlohr profile image
Alex Lohr

Just checked again, that does not work either.

 
madsstoumann profile image
Mads Stoumann

That’s, unfortunately, the issue: it doesn’t work!

Collapse
 
siddharthshyniben profile image
Siddharth

It's actually not the exact same thing, there's supposed to be a pulse when we click it. Realy nice though!

Collapse
 
madsstoumann profile image
Mads Stoumann

Thx! I didn’t look into animations, I’ll update the examples later