Let's say we're given the following mock from a designer to list files in rows.
Each row should be clickable. There is also a button of "other options" on each row that triggers a different event. Therefore, there are two clickable elements, one which appears to encapsulate the other.
I'm trying to be better at semantic HTMl so I initially wrote out a <button>
, stripped it of its default styling and made it into row. Then I nested another <button>
inside. That is when I experienced the react warning <button> cannot appear as a descendant of <button>
.
I learned that for the HTML button there must be no interactive content descendant. Interactive content is content that is specifically intended for user interaction.
We are left with two options:
- Transform a non-semantic
<div>
into a clickable element - Use styling to place one
<button>
on top of another
The first is completely possible. We simply have to include a few aria attributes for accessibility. The div might look something like this
<div tabindex="0" role="button">
<div>file title</div>
<button>other options</button>
</div>
The other option was a little trickier but felt better to me. I don't claim to know all the ins and outs of semantic HTML but as I mentioned I'm increasingly trying to use the right tags wherever possible.
<div class='two-buttons'>
<button class='row undo-button-styling'>
<div>File 🤖 🎃</div>
</button>
<button class='other-options'>other options</button>
</div>
There are a number of styling changes that need to happen (position relative parent, position absolute child, undoing button styling) but here is the finished codepen.
Top comments (4)
I would have gone with the Div approach.
If you can't do it in plain Js out of the box, it's probably not the best option. Unless it has some other benefit (like a lot less code).
jsfiddle.net/athomsfere/35wakz2j/1/
I love seeing raw JS solutions like this. Too much we get lost in frameworks and it's a good reminder.
I believe the weakness of this solution is its inaccessibility. For example there are no tabs on the clickable rows. Additionally, screen readers will not register that the divs are serving as buttons.
True, but I'd also say:
Scrolling through the page, it doesn't look like a button either. (I guess this is why I went straight to adding a hover effect).
Tabbable == fixable at least.
But I guess back to my original point: I tent to prototype the big idea in pure JS. And then move it to a framework or rewrite it as a reusable component where I can continue to work through enhancements like accessibility.
But why it is invalid, can anyone tell, what bugs will it cause