# Selectable Users Table

> A users table with row checkboxes, a select-all header box and a live selected count.

- Kind: Element
- Page: https://ownlyplans.com/bhaskar/selectable-users-table/
- Licence: MIT (do anything, keep the notice)

## Code

`index.html`

```html
<div class='tb'><div class='th'><h4>Users</h4><span id='usc'>1 selected</span></div><table><thead><tr><th><span class='ck' id='usa'></span></th><th>Name</th><th>Email</th><th>Role</th></tr></thead><tbody id='usb'></tbody></table></div>
```

`styles.css`

```css
.tb{width:min(580px,96%);margin:auto;background:#fff;border:1px solid #e8e8e8;border-radius:16px;overflow:hidden;font-family:Inter,Arial,sans-serif;color:#111}.th{display:flex;justify-content:space-between;align-items:center;padding:16px 18px 12px}.th h4{margin:0;font-size:15px;font-weight:600}.th span{font-size:13px;color:#737373}.tb table{width:100%;border-collapse:collapse}.tb th{padding:11px 14px;font-size:12.5px;font-weight:500;color:#737373;text-align:left;border-top:1px solid #f0f0f0}.tb td{padding:12px 14px;font-size:14px;border-top:1px solid #f4f4f4}.tb tr.sel td{background:#f8f8f8}.tb td:nth-child(3){color:#737373}.tb td:nth-child(2){font-weight:500}.ck{display:grid;place-items:center;width:17px;height:17px;border:1.5px solid #d4d4d4;border-radius:5px;background:#fff;cursor:pointer;transition:all .15s}.ck.on,.ck.mid{background:#111;border-color:#111}.ck.on:after{content:'';width:4px;height:8px;border:solid #fff;border-width:0 2px 2px 0;transform:rotate(45deg) translate(-1px,-1px)}.ck.mid:after{content:'';width:8px;height:2px;background:#fff;border-radius:2px}
```

`script.js`

```js
const U=[['Arun Kapoor','arun@studio.dev','Admin',1],['Rupam Sen','rupam@studio.dev','Editor',0],['Ava Chen','ava@studio.dev','Viewer',0],['Sofia Ortiz','sofia@studio.dev','Editor',0]];const tb=document.getElementById('usb'),all=document.getElementById('usa'),c=document.getElementById('usc');const draw=()=>{tb.innerHTML=U.map((u,i)=>'<tr class="'+(u[3]?'sel':'')+'"><td><span class="ck '+(u[3]?'on':'')+'" data-i='+i+'></span></td><td>'+u[0]+'</td><td>'+u[1]+'</td><td>'+u[2]+'</td></tr>').join('');const n=U.filter(u=>u[3]).length;all.className='ck '+(n===U.length?'on':n?'mid':'');c.textContent=n+' selected'};tb.addEventListener('click',e=>{const k=e.target.closest('.ck');if(k){U[+k.dataset.i][3]^=1;draw()}});all.addEventListener('click',()=>{const v=U.every(u=>u[3])?0:1;U.forEach(u=>u[3]=v);draw()});draw();
```

## About

Tick rows to highlight them and update the 1 selected counter. The header box becomes indeterminate for partial selections and toggles all.

---
Also available as JSON: https://ownlyplans.com/bhaskar/selectable-users-table/?format=json
MCP server: https://ownlyplans.com/mcp
