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.