JSFiddle - React, Tailwind, and code Playground
HTML
<button onclick="SwapAll(false);">Свернуть всё</button>   <button onclick="SwapAll(true);">Развернуть всё</button>
<br><br>
<table id="MyTable">
<tr><th>Фамилия</th> <th>Проект</th> <th>Задача</th> <th>План</th> <th>Факт</th></tr>
<tr> <td> <label><input type="checkbox"><a onclick="sh(this)">Иванов</a></label> </td> <td></td> <td></td> <td></td> <td></td> </tr>
<tr><td colspan=5 class="node">
<input type="checkbox">
<table>
<tr> <td></td> <td> <label><input type="checkbox"><a onclick="sh(this)">Проект 1</a></label></td> <td></td> <td></td> <td></td> </tr>
<tr><td colspan=5 class="node">
<input type="checkbox">
<table>
<tr> <td></td> <td></td> <td>Задача 1</td> <td>10</td> <td>11</td> </tr>
<tr> <td></td> <td></td> <td>Задача 2</td> <td>20</td> <td>21</td> </tr>
<tr> <td></td> <td></td> <td>Задача 3</td> <td>30</td> <td>31</td> </tr>
</table>
</td></tr>
</table>
<table>
<tr> <td></td> <td> <label><input type="checkbox"><a onclick="sh(this)">Проект 2</a></label></td> <td></td> <td></td> <td></td> </tr>
<tr><td colspan=5 class="node">
<input type="checkbox">
<table>
<tr> <td></td> <td></td> <td>Задача 2_1</td> <td>25</td> <td>27</td> </tr>
<tr> <td></td> <td></td> <td>Задача 2_2</td> <td>45</td> <td>47</td> </tr>
</table>
</td></tr>
</table>
</td></tr>
<tr> <td> <label><input type="checkbox"><a onclick="sh(this)">Петров</a></label> </td> <td></td> <td></td> <td></td> <td></td> </tr>
<tr><td colspan=5 class="node">
<input type="checkbox">
<table>
<tr> <td></td> <td> <label><input type="checkbox"><a onclick="sh(this)">Проект 3</a></label></td> <td></td> <td></td> <td></td> </tr>
<tr><td colspan=5 class="node">
<input type="checkbox">
<table>
<tr> <td></td> <td></td> <td>Задача 3_1</td> <td>100</td> <td>110</td> </tr>
<tr> <td></td> <td></td> <td>Задача 3_2</td> <td>200</td> <td>210</td> </tr>
<tr> <td></td> <td></td> <td>Задача 3_3</td> <td>300</td>...
CSS
table {
border-collapse:collapse;
table-layout:fixed;
width:560px;
}
td, th {
border:1px solid gray;
border-top:0;
padding:2px 5px;
width:100px;
}
th {
background:#ccc;
border-top:1px solid gray;
}
input{
display:none;
}
input + a {
background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAALCAIAAAAmzuBxAAAACXBIWXMAAAsSAAALEgHS3X78AAAAkElEQVQYlXWOvRWDQAyDv/DYK2wQSro8OkpGuRFcUjJCRmEE0TldCpsjPy9qzj7Jki62Pgh4vnqbbbEWuN+use/PlArwHccWGg780psENGFY6W4YgxZIAM339WmT3m397YYxxn6aASslFfVotYLTT3NwcuTKlFpNR2sdEak4acdKeafPlE2SZ7sw/1BEtX94AXYTVmyR94mPAAAAAElFTkSuQmCC)
no-repeat 0px 4px;
}
input:checked + a {
background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAALCAIAAAAmzuBxAAAACXBIWXMAAAsSAAALEgHS3X78AAAAeklEQVQYlX2PsRGDMAxFX3zeK9mAlHRcupSM4hFUUjJCRpI70VHIJr7D8BtJ977+SQ9Zf7isVG16WSQC0/D0OW/FqoBlDFkIVJ2xAhA8sI/NHbcYiFrPfI0fGklKagDx2F4ltdtaM0J9L3dxcVxi+zv62E+MwPs7c60dClRP6iug7wUAAAAASUVORK5CYII=)
no-repeat 0px 4px;
}
label a {
cursor:pointer;
padding-left:16px;
}
input ~ table {
display:none;
}
input:checked ~ table {
display:table;
margin-top:-1px;
margin-left:-1px;
}
.node {
padding:0;
border-bottom:0;
}
td+td+td+td {text-align:right;}
JavaScript
function sh(el) {
var row = el.parentNode.parentNode.parentNode;
var nextRow = row.parentNode.rows[row.rowIndex + 1];
var chk = nextRow.querySelector('td > input');
chk.checked = !chk.checked;
}
function SwapAll(b) {
var tbl = document.getElementById('MyTable');
var chks = tbl.getElementsByTagName('input');
for (var i=0; i<chks.length; i++) {
chks[i].checked = b;
}
}