Open demo

CSS code

HTML
<section id="saved-view-table" class="sv" aria-labelledby="sv-title">
 <header class="sv-head"><div><p class="sv-kicker">FIELDWORK / ORDER OPERATIONS</p><h2 class="" id="sv-title">A view for every workflow.</h2><p class="sv-sub">Filter the work. Save your view. Move the right orders forward.</p></div><div class="sv-actions"><button type="button" class="sv-button" id="sv-export" >Export CSV</button><button type="button" class="sv-button primary" id="sv-save" >Save this view</button></div></header>
 <div class="sv-tools"><div class="sv-field"><label class="" for="sv-view">Saved view</label><select class="" id="sv-view"><option>All orders</option><option>Needs review</option></select></div><div class="sv-field grow"><label class="" for="sv-search">Search orders</label><input class="" id="sv-search" type="search" placeholder="Order, customer or email"></div><div class="sv-field"><label class="" for="sv-state">Status</label><select class="" id="sv-state"><option>All statuses</option><option>Review</option><option>Ready</option><option>Archived</option></select></div><div class="sv-field"><label class="" for="sv-owner">Owner</label><select class="" id="sv-owner"><option>All owners</option><option>Mira</option><option>James</option><option>Avery</option></select></div><button type="button" class="sv-button" id="sv-delete" disabled>Delete view</button></div>
 <div class="sv-bulk" id="sv-bulk" hidden><span class="sv-count" id="sv-selected"></span><button type="button" class="sv-button" id="sv-ready" >Mark ready</button><button type="button" class="sv-button" id="sv-archive" >Archive selected</button><button type="button" class="sv-button" id="sv-clear" >Clear selection</button></div>
 <div class="sv-scroll" tabindex="0" role="region" aria-label="Scrollable orders table"><table class=""><caption>Orders with saved filters, sorting, page selection and bulk status actions</caption><thead><tr><th scope="col"><input class="" type="checkbox" id="sv-all" aria-label="Select all orders on this page"></th><th scope="col" id="sv-sort-id" aria-sort="ascending"><button type="button" data-sort="id">Order ↕</button></th><th scope="col">Customer</th><th scope="col">Owner</th><th scope="col">Status</th><th scope="col" id="sv-sort-total"><button type="button" data-sort="total">Total ↕</button></th></tr></thead><tbody id="sv-rows"></tbody></table></div>
 <div class="sv-footer"><p id="sv-page-count"></p><div class="sv-actions"><label class="" for="sv-page-size">Rows per page</label><select class="" style="width:auto" id="sv-page-size"><option>4</option><option>8</option><option>12</option></select><button type="button" class="sv-button" id="sv-prev" >Previous</button><button type="button" class="sv-button" id="sv-next" >Next</button></div></div><p class="sv-info">Selection spans pages of the current filter. Changing a filter clears selection. Views and demo changes save in this browser.</p><p class="sv-status" id="sv-status" role="status" aria-live="polite"></p>
 <dialog class="" id="sv-dialog" aria-labelledby="sv-dialog-title"><h3 class="" id="sv-dialog-title">Save this view</h3><p class="sv-sub">Remember the current search, status, owner, sort and page size.</p><form id="sv-view-form"><div class="sv-field"><label class="" for="sv-view-name">View name</label><input class="" type="text" id="sv-view-name" required maxlength="40" placeholder="Mira’s review queue"></div><p class="sv-status" id="sv-error" role="alert"></p><div class="sv-actions"><button class="sv-button primary" type="submit">Save view</button><button type="button" class="sv-button" id="sv-cancel" >Cancel</button></div></form></dialog>
</section>
CSS
.sv{--sv-ink:#1d293b;--sv-muted:#526176;--sv-accent:#4338a2;--sv-line:#d9dfea;color:var(--sv-ink);font:13px/1.5 system-ui,sans-serif;background:white;border:1px solid var(--sv-line);border-radius:12px;overflow:hidden;width:100%}.sv *{box-sizing:border-box}.sv h2,.sv h3,.sv p{margin:0}.sv h2{font-size:20px;letter-spacing:-.5px;font-weight:700}.sv h3{font-size:18px;font-weight:700}.sv-head{padding:24px;display:flex;justify-content:space-between;align-items:center;gap:16px}.sv-sub{font-size:12px;color:var(--sv-muted);margin-top:4px!important}.sv-kicker{font-size:10px;font-weight:750;letter-spacing:1.7px;color:var(--sv-accent);margin-bottom:8px!important}.sv-tools{display:flex;gap:12px;flex-wrap:wrap;align-items:end;border-top:1px solid var(--sv-line);border-bottom:1px solid var(--sv-line);padding:17px 24px;background:#f8f9fc}.sv-field{min-width:120px;flex:1}.sv-field.grow{flex:2;min-width:180px}.sv label{display:block;font-size:11px;font-weight:650;margin-bottom:5px}.sv input:not([type=checkbox]),.sv select{display:block;width:100%;height:38px;border:1px solid #97a3b6;border-radius:6px;background:#fff;color:var(--sv-ink);padding:7px 10px;font:inherit}.sv input[type=checkbox]{width:16px;height:16px;accent-color:var(--sv-accent)}.sv-button{display:inline-flex;align-items:center;justify-content:center;gap:5px;border:1px solid #97a3b6;background:white;color:var(--sv-ink);border-radius:6px;padding:8px 12px;font-size:12px;font-weight:600;min-height:36px;cursor:pointer;white-space:nowrap;text-decoration:none}.sv-button.primary{background:var(--sv-accent);color:#fff;border-color:var(--sv-accent)}.sv-button:disabled{opacity:.5;cursor:not-allowed}.sv button:focus-visible,.sv input:focus-visible,.sv select:focus-visible,.sv a:focus-visible,.sv [tabindex]:focus-visible{outline:3px solid #4338a2;outline-offset:2px}.sv-actions{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.sv-bulk{background:#eeecfb;padding:12px 24px;display:flex;gap:12px;align-items:center;flex-wrap:wrap}.sv-bulk[hidden]{display:none}.sv-count{font-size:12px;font-weight:650;margin-right:auto}.sv-scroll{overflow:auto;max-width:100%}.sv table{border-collapse:collapse;width:100%;font:12px/1.5 system-ui,sans-serif;margin:0}.sv caption{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.sv th,.sv td{padding:15px 20px;border-bottom:1px solid var(--sv-line);text-align:left;white-space:nowrap;vertical-align:middle}.sv th{font-size:10px;letter-spacing:.6px;text-transform:uppercase;color:var(--sv-muted);font-weight:650;background:white}.sv th:first-child,.sv td:first-child{width:42px;padding-right:0}.sv th button{background:none;border:0;padding:0;color:inherit;font:inherit;cursor:pointer}.sv td strong{font-weight:650;display:block}.sv td small{font-size:10px;color:var(--sv-muted);display:block}.sv .sv-num{font-variant-numeric:tabular-nums;font-family:ui-monospace,monospace}.sv tr[data-selected=true] td{background:#f2f0fc}.sv-tag{display:inline-flex;border-radius:5px;padding:4px 8px;background:#f0f2f6;color:#445166;font-size:10px;font-weight:650}.sv-tag.ready{background:#e3f3e9;color:#186344}.sv-tag.review{background:#fff0d5;color:#7b4911}.sv-footer{display:flex;justify-content:space-between;gap:12px;align-items:center;padding:17px 24px;flex-wrap:wrap}.sv-footer p{color:var(--sv-muted);font-size:11px}.sv-info{padding:0 24px 18px;color:var(--sv-muted);font-size:11px}.sv dialog{width:min(430px,calc(100% - 30px));background:white;color:var(--sv-ink);border:1px solid var(--sv-line);border-radius:12px;padding:24px}.sv dialog::backdrop{background:#17243b80}.sv dialog .sv-field{margin:18px 0}.sv-status{padding:0 24px 18px;font-size:12px;color:var(--sv-accent)}.sv-status:empty{display:none}.sv-empty{text-align:center;padding:28px;color:var(--sv-muted)}@media(max-width:550px){.sv-head{padding:18px;align-items:start;flex-direction:column}.sv-tools{padding:16px}.sv-field.grow{flex-basis:100%}.sv th,.sv td{padding:13px 14px}.sv-bulk,.sv-footer{padding:14px 16px}.sv-info{padding:0 16px 16px}}
JavaScript
(()=>{'use strict';const root=document.querySelector('#saved-view-table');if(!root)return;const $=s=>root.querySelector(s),$$=s=>[...root.querySelectorAll(s)];const KEY='uic-table-saved-views-23';const esc=s=>String(s).replace(/[&<>"']/g,c=>({'&':'&','<':'<','>':'>','"':'"',"'":'''}[c]));const initial=[{"id":"ORD-1082","customer":"Hana Kim","email":"[email protected]","owner":"Mira","status":"Review","total":280},{"id":"ORD-1083","customer":"Leo Bennett","email":"[email protected]","owner":"James","status":"Ready","total":145},{"id":"ORD-1084","customer":"Amara Okafor","email":"[email protected]","owner":"Mira","status":"Review","total":620},{"id":"ORD-1085","customer":"Nora Ellis","email":"[email protected]","owner":"Avery","status":"Ready","total":96},{"id":"ORD-1086","customer":"Priya Shah","email":"[email protected]","owner":"James","status":"Review","total":340},{"id":"ORD-1087","customer":"Ravi Kapoor","email":"[email protected]","owner":"Mira","status":"Ready","total":192},{"id":"ORD-1088","customer":"Sofia Reyes","email":"[email protected]","owner":"Avery","status":"Review","total":455},{"id":"ORD-1089","customer":"Omar Haddad","email":"[email protected]","owner":"James","status":"Ready","total":85},{"id":"ORD-1090","customer":"Clara Dubois","email":"[email protected]","owner":"Mira","status":"Review","total":760},{"id":"ORD-1091","customer":"Theo Walsh","email":"[email protected]","owner":"Avery","status":"Ready","total":120},{"id":"ORD-1092","customer":"Mei Tan","email":"[email protected]","owner":"James","status":"Review","total":215},{"id":"ORD-1093","customer":"Kai Osei","email":"[email protected]","owner":"Mira","status":"Ready","total":410}];const defaults=[{name:'All orders',query:'',status:'All statuses',owner:'All owners',sort:'id',ascending:true,size:4},{name:'Needs review',query:'',status:'Review',owner:'All owners',sort:'id',ascending:true,size:4}];let records=structuredClone(initial),views=structuredClone(defaults);try{const saved=JSON.parse(localStorage.getItem(KEY));if(saved&&Array.isArray(saved.records)&&Array.isArray(saved.views)){records=saved.records;views=[...defaults,...saved.views.filter(v=>!defaults.some(d=>d.name===v.name))];}}catch{}let selected=new Set(),page=0,sort='id',ascending=true;const say=s=>$('#sv-status').textContent=s;const persist=()=>{try{localStorage.setItem(KEY,JSON.stringify({records,views:views.slice(2)}));return true;}catch{say('Browser storage is unavailable. Changes last for this tab only.');return false;}};const state=()=>({query:$('#sv-search').value,status:$('#sv-state').value,owner:$('#sv-owner').value,sort,ascending,size:+$('#sv-page-size').value});const filtered=()=>records.filter(r=>(r.id+' '+r.customer+' '+r.email).toLowerCase().includes($('#sv-search').value.toLowerCase())&&($('#sv-state').value==='All statuses'||r.status===$('#sv-state').value)&&($('#sv-owner').value==='All owners'||r.owner===$('#sv-owner').value)).sort((a,b)=>(sort==='total'?a.total-b.total:a.id.localeCompare(b.id))*(ascending?1:-1));function viewOptions(value='All orders'){$('#sv-view').innerHTML=views.map(v=>'<option>'+esc(v.name)+'</option>').join('');$('#sv-view').value=value;$('#sv-delete').disabled=!views.slice(2).some(v=>v.name===value);}function render(){const rows=filtered(),size=+$('#sv-page-size').value;page=Math.min(page,Math.max(0,Math.ceil(rows.length/size)-1));const visible=rows.slice(page*size,page*size+size);$('#sv-rows').innerHTML=visible.map(r=>'<tr class="" data-selected="'+selected.has(r.id)+'"><td class=""><input class="" type="checkbox" data-row="'+r.id+'" aria-label="Select '+r.id+'" '+(selected.has(r.id)?'checked':'')+'></td><td class=""><strong class="sv-num">'+r.id+'</strong></td><td class=""><strong class="">'+esc(r.customer)+'</strong><small class="">'+esc(r.email)+'</small></td><td class="">'+r.owner+'</td><td class=""><span class="sv-tag '+r.status.toLowerCase()+'">'+r.status+'</span></td><td class=" sv-num">$'+r.total.toFixed(2)+'</td></tr>').join('')||'<tr><td colspan="6" class="sv-empty">No matching orders. Clear the search or change your filters.</td></tr>';$('#sv-page-count').textContent=rows.length?'Showing '+(page*size+1)+'–'+Math.min(page*size+size,rows.length)+' of '+rows.length+' orders':'0 orders';$('#sv-prev').disabled=page===0;$('#sv-next').disabled=(page+1)*size>=rows.length;$('#sv-all').disabled=!visible.length;$('#sv-all').checked=visible.length>0&&visible.every(r=>selected.has(r.id));$('#sv-all').indeterminate=visible.some(r=>selected.has(r.id))&&!$('#sv-all').checked;$('#sv-bulk').hidden=selected.size===0;$('#sv-selected').textContent=selected.size+' order'+(selected.size===1?'':'s')+' selected';$$('[data-sort]').forEach(b=>{const th=b.closest('th');if(b.dataset.sort===sort)th.setAttribute('aria-sort',ascending?'ascending':'descending');else th.removeAttribute('aria-sort');});$$('[data-row]').forEach(c=>c.onchange=()=>{c.checked?selected.add(c.dataset.row):selected.delete(c.dataset.row);render()});}
function filtersChanged(){selected.clear();page=0;$('#sv-view').selectedIndex=-1;$('#sv-delete').disabled=true;render();}['sv-search','sv-state','sv-owner'].forEach(id=>$('#'+id).addEventListener('input',filtersChanged));$('#sv-page-size').onchange=()=>{page=0;render()};$$('[data-sort]').forEach(b=>b.onclick=()=>{ascending=b.dataset.sort===sort?!ascending:true;sort=b.dataset.sort;render()});$('#sv-prev').onclick=()=>{page--;render()};$('#sv-next').onclick=()=>{page++;render()};$('#sv-all').onchange=()=>{const size=+$('#sv-page-size').value;filtered().slice(page*size,page*size+size).forEach(r=>$('#sv-all').checked?selected.add(r.id):selected.delete(r.id));render()};$('#sv-clear').onclick=()=>{selected.clear();render();say('Selection cleared.')};function bulk(status){const n=selected.size;records.forEach(r=>{if(selected.has(r.id))r.status=status});selected.clear();const saved=persist();render();say(n+' orders moved to '+status+'.'+(saved?' Saved in this browser.':' Changes last for this tab only.'));}$('#sv-ready').onclick=()=>bulk('Ready');$('#sv-archive').onclick=()=>bulk('Archived');$('#sv-view').onchange=()=>{const v=views.find(v=>v.name===$('#sv-view').value);if(!v)return;$('#sv-search').value=v.query;$('#sv-state').value=v.status;$('#sv-owner').value=v.owner;$('#sv-page-size').value=v.size;sort=v.sort;ascending=v.ascending;page=0;selected.clear();$('#sv-delete').disabled=defaults.some(d=>d.name===v.name);render();say(v.name+' view applied.')};$('#sv-save').onclick=()=>{$('#sv-error').textContent='';$('#sv-view-name').value='';$('#sv-dialog').showModal()};$('#sv-cancel').onclick=()=>$('#sv-dialog').close();$('#sv-view-form').onsubmit=e=>{e.preventDefault();if(!e.currentTarget.reportValidity())return;const name=$('#sv-view-name').value.trim();if(!name){$('#sv-error').textContent='Enter a view name.';return;}if(views.some(v=>v.name.toLowerCase()===name.toLowerCase())){$('#sv-error').textContent='Choose a different name; this view already exists.';return;}views.push({name,...state()});const saved=persist();viewOptions(name);$('#sv-dialog').close();say(saved?'View saved in this browser.':'View created for this tab only.');};$('#sv-delete').onclick=()=>{const name=$('#sv-view').value;if(defaults.some(v=>v.name===name))return;views=views.filter(v=>v.name!==name);persist();viewOptions();$('#sv-view').dispatchEvent(new Event('change'));say('Custom view deleted. Default views remain available.')};$('#sv-export').onclick=()=>{const cell=x=>'"'+String(x).replace(/^[=+@-]/,"'$&").replaceAll('"','""')+'"';const text='\uFEFF'+[['Order','Customer','Email','Owner','Status','Total'],...filtered().map(r=>[r.id,r.customer,r.email,r.owner,r.status,r.total.toFixed(2)])].map(row=>row.map(cell).join(',')).join('\r\n');const url=URL.createObjectURL(new Blob([text],{type:'text/csv;charset=utf-8'}));const a=document.createElement('a');a.href=url;a.download='filtered-orders.csv';a.click();setTimeout(()=>URL.revokeObjectURL(url),1000);say('Filtered orders exported as CSV.')};viewOptions();render();})();

Bootstrap 5 code

Requires: Bootstrap 5.3.8 CSS

HTML
<section id="saved-view-table" class="sv card" aria-labelledby="sv-title">
 <header class="sv-head"><div><p class="sv-kicker">FIELDWORK / ORDER OPERATIONS</p><h2 class="" id="sv-title">A view for every workflow.</h2><p class="sv-sub">Filter the work. Save your view. Move the right orders forward.</p></div><div class="sv-actions"><button type="button" class="sv-button" id="sv-export" >Export CSV</button><button type="button" class="sv-button primary" id="sv-save" >Save this view</button></div></header>
 <div class="sv-tools"><div class="sv-field"><label class="" for="sv-view">Saved view</label><select class="form-control" id="sv-view"><option>All orders</option><option>Needs review</option></select></div><div class="sv-field grow"><label class="" for="sv-search">Search orders</label><input class="form-control" id="sv-search" type="search" placeholder="Order, customer or email"></div><div class="sv-field"><label class="" for="sv-state">Status</label><select class="form-control" id="sv-state"><option>All statuses</option><option>Review</option><option>Ready</option><option>Archived</option></select></div><div class="sv-field"><label class="" for="sv-owner">Owner</label><select class="form-control" id="sv-owner"><option>All owners</option><option>Mira</option><option>James</option><option>Avery</option></select></div><button type="button" class="sv-button" id="sv-delete" disabled>Delete view</button></div>
 <div class="sv-bulk" id="sv-bulk" hidden><span class="sv-count" id="sv-selected"></span><button type="button" class="sv-button" id="sv-ready" >Mark ready</button><button type="button" class="sv-button" id="sv-archive" >Archive selected</button><button type="button" class="sv-button" id="sv-clear" >Clear selection</button></div>
 <div class="sv-scroll" tabindex="0" role="region" aria-label="Scrollable orders table"><table class="table"><caption>Orders with saved filters, sorting, page selection and bulk status actions</caption><thead><tr><th scope="col"><input class="form-check-input" type="checkbox" id="sv-all" aria-label="Select all orders on this page"></th><th scope="col" id="sv-sort-id" aria-sort="ascending"><button type="button" data-sort="id">Order ↕</button></th><th scope="col">Customer</th><th scope="col">Owner</th><th scope="col">Status</th><th scope="col" id="sv-sort-total"><button type="button" data-sort="total">Total ↕</button></th></tr></thead><tbody id="sv-rows"></tbody></table></div>
 <div class="sv-footer"><p id="sv-page-count"></p><div class="sv-actions"><label class="" for="sv-page-size">Rows per page</label><select class="form-control" style="width:auto" id="sv-page-size"><option>4</option><option>8</option><option>12</option></select><button type="button" class="sv-button" id="sv-prev" >Previous</button><button type="button" class="sv-button" id="sv-next" >Next</button></div></div><p class="sv-info">Selection spans pages of the current filter. Changing a filter clears selection. Views and demo changes save in this browser.</p><p class="sv-status" id="sv-status" role="status" aria-live="polite"></p>
 <dialog class="" id="sv-dialog" aria-labelledby="sv-dialog-title"><h3 class="" id="sv-dialog-title">Save this view</h3><p class="sv-sub">Remember the current search, status, owner, sort and page size.</p><form id="sv-view-form"><div class="sv-field"><label class="" for="sv-view-name">View name</label><input class="form-control" type="text" id="sv-view-name" required maxlength="40" placeholder="Mira’s review queue"></div><p class="sv-status" id="sv-error" role="alert"></p><div class="sv-actions"><button class="sv-button primary" type="submit">Save view</button><button type="button" class="sv-button" id="sv-cancel" >Cancel</button></div></form></dialog>
</section>
CSS
.sv{--sv-ink:#1d293b;--sv-muted:#526176;--sv-accent:#4338a2;--sv-line:#d9dfea;color:var(--sv-ink);font:13px/1.5 system-ui,sans-serif;background:white;border:1px solid var(--sv-line);border-radius:12px;overflow:hidden;width:100%}.sv *{box-sizing:border-box}.sv h2,.sv h3,.sv p{margin:0}.sv h2{font-size:20px;letter-spacing:-.5px;font-weight:700}.sv h3{font-size:18px;font-weight:700}.sv-head{padding:24px;display:flex;justify-content:space-between;align-items:center;gap:16px}.sv-sub{font-size:12px;color:var(--sv-muted);margin-top:4px!important}.sv-kicker{font-size:10px;font-weight:750;letter-spacing:1.7px;color:var(--sv-accent);margin-bottom:8px!important}.sv-tools{display:flex;gap:12px;flex-wrap:wrap;align-items:end;border-top:1px solid var(--sv-line);border-bottom:1px solid var(--sv-line);padding:17px 24px;background:#f8f9fc}.sv-field{min-width:120px;flex:1}.sv-field.grow{flex:2;min-width:180px}.sv label{display:block;font-size:11px;font-weight:650;margin-bottom:5px}.sv input:not([type=checkbox]),.sv select{display:block;width:100%;height:38px;border:1px solid #97a3b6;border-radius:6px;background:#fff;color:var(--sv-ink);padding:7px 10px;font:inherit}.sv input[type=checkbox]{width:16px;height:16px;accent-color:var(--sv-accent)}.sv-button{display:inline-flex;align-items:center;justify-content:center;gap:5px;border:1px solid #97a3b6;background:white;color:var(--sv-ink);border-radius:6px;padding:8px 12px;font-size:12px;font-weight:600;min-height:36px;cursor:pointer;white-space:nowrap;text-decoration:none}.sv-button.primary{background:var(--sv-accent);color:#fff;border-color:var(--sv-accent)}.sv-button:disabled{opacity:.5;cursor:not-allowed}.sv button:focus-visible,.sv input:focus-visible,.sv select:focus-visible,.sv a:focus-visible,.sv [tabindex]:focus-visible{outline:3px solid #4338a2;outline-offset:2px}.sv-actions{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.sv-bulk{background:#eeecfb;padding:12px 24px;display:flex;gap:12px;align-items:center;flex-wrap:wrap}.sv-bulk[hidden]{display:none}.sv-count{font-size:12px;font-weight:650;margin-right:auto}.sv-scroll{overflow:auto;max-width:100%}.sv table{border-collapse:collapse;width:100%;font:12px/1.5 system-ui,sans-serif;margin:0}.sv caption{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.sv th,.sv td{padding:15px 20px;border-bottom:1px solid var(--sv-line);text-align:left;white-space:nowrap;vertical-align:middle}.sv th{font-size:10px;letter-spacing:.6px;text-transform:uppercase;color:var(--sv-muted);font-weight:650;background:white}.sv th:first-child,.sv td:first-child{width:42px;padding-right:0}.sv th button{background:none;border:0;padding:0;color:inherit;font:inherit;cursor:pointer}.sv td strong{font-weight:650;display:block}.sv td small{font-size:10px;color:var(--sv-muted);display:block}.sv .sv-num{font-variant-numeric:tabular-nums;font-family:ui-monospace,monospace}.sv tr[data-selected=true] td{background:#f2f0fc}.sv-tag{display:inline-flex;border-radius:5px;padding:4px 8px;background:#f0f2f6;color:#445166;font-size:10px;font-weight:650}.sv-tag.ready{background:#e3f3e9;color:#186344}.sv-tag.review{background:#fff0d5;color:#7b4911}.sv-footer{display:flex;justify-content:space-between;gap:12px;align-items:center;padding:17px 24px;flex-wrap:wrap}.sv-footer p{color:var(--sv-muted);font-size:11px}.sv-info{padding:0 24px 18px;color:var(--sv-muted);font-size:11px}.sv dialog{width:min(430px,calc(100% - 30px));background:white;color:var(--sv-ink);border:1px solid var(--sv-line);border-radius:12px;padding:24px}.sv dialog::backdrop{background:#17243b80}.sv dialog .sv-field{margin:18px 0}.sv-status{padding:0 24px 18px;font-size:12px;color:var(--sv-accent)}.sv-status:empty{display:none}.sv-empty{text-align:center;padding:28px;color:var(--sv-muted)}@media(max-width:550px){.sv-head{padding:18px;align-items:start;flex-direction:column}.sv-tools{padding:16px}.sv-field.grow{flex-basis:100%}.sv th,.sv td{padding:13px 14px}.sv-bulk,.sv-footer{padding:14px 16px}.sv-info{padding:0 16px 16px}}
JavaScript
(()=>{'use strict';const root=document.querySelector('#saved-view-table');if(!root)return;const $=s=>root.querySelector(s),$$=s=>[...root.querySelectorAll(s)];const KEY='uic-table-saved-views-23';const esc=s=>String(s).replace(/[&<>"']/g,c=>({'&':'&','<':'<','>':'>','"':'"',"'":'''}[c]));const initial=[{"id":"ORD-1082","customer":"Hana Kim","email":"[email protected]","owner":"Mira","status":"Review","total":280},{"id":"ORD-1083","customer":"Leo Bennett","email":"[email protected]","owner":"James","status":"Ready","total":145},{"id":"ORD-1084","customer":"Amara Okafor","email":"[email protected]","owner":"Mira","status":"Review","total":620},{"id":"ORD-1085","customer":"Nora Ellis","email":"[email protected]","owner":"Avery","status":"Ready","total":96},{"id":"ORD-1086","customer":"Priya Shah","email":"[email protected]","owner":"James","status":"Review","total":340},{"id":"ORD-1087","customer":"Ravi Kapoor","email":"[email protected]","owner":"Mira","status":"Ready","total":192},{"id":"ORD-1088","customer":"Sofia Reyes","email":"[email protected]","owner":"Avery","status":"Review","total":455},{"id":"ORD-1089","customer":"Omar Haddad","email":"[email protected]","owner":"James","status":"Ready","total":85},{"id":"ORD-1090","customer":"Clara Dubois","email":"[email protected]","owner":"Mira","status":"Review","total":760},{"id":"ORD-1091","customer":"Theo Walsh","email":"[email protected]","owner":"Avery","status":"Ready","total":120},{"id":"ORD-1092","customer":"Mei Tan","email":"[email protected]","owner":"James","status":"Review","total":215},{"id":"ORD-1093","customer":"Kai Osei","email":"[email protected]","owner":"Mira","status":"Ready","total":410}];const defaults=[{name:'All orders',query:'',status:'All statuses',owner:'All owners',sort:'id',ascending:true,size:4},{name:'Needs review',query:'',status:'Review',owner:'All owners',sort:'id',ascending:true,size:4}];let records=structuredClone(initial),views=structuredClone(defaults);try{const saved=JSON.parse(localStorage.getItem(KEY));if(saved&&Array.isArray(saved.records)&&Array.isArray(saved.views)){records=saved.records;views=[...defaults,...saved.views.filter(v=>!defaults.some(d=>d.name===v.name))];}}catch{}let selected=new Set(),page=0,sort='id',ascending=true;const say=s=>$('#sv-status').textContent=s;const persist=()=>{try{localStorage.setItem(KEY,JSON.stringify({records,views:views.slice(2)}));return true;}catch{say('Browser storage is unavailable. Changes last for this tab only.');return false;}};const state=()=>({query:$('#sv-search').value,status:$('#sv-state').value,owner:$('#sv-owner').value,sort,ascending,size:+$('#sv-page-size').value});const filtered=()=>records.filter(r=>(r.id+' '+r.customer+' '+r.email).toLowerCase().includes($('#sv-search').value.toLowerCase())&&($('#sv-state').value==='All statuses'||r.status===$('#sv-state').value)&&($('#sv-owner').value==='All owners'||r.owner===$('#sv-owner').value)).sort((a,b)=>(sort==='total'?a.total-b.total:a.id.localeCompare(b.id))*(ascending?1:-1));function viewOptions(value='All orders'){$('#sv-view').innerHTML=views.map(v=>'<option>'+esc(v.name)+'</option>').join('');$('#sv-view').value=value;$('#sv-delete').disabled=!views.slice(2).some(v=>v.name===value);}function render(){const rows=filtered(),size=+$('#sv-page-size').value;page=Math.min(page,Math.max(0,Math.ceil(rows.length/size)-1));const visible=rows.slice(page*size,page*size+size);$('#sv-rows').innerHTML=visible.map(r=>'<tr class="" data-selected="'+selected.has(r.id)+'"><td class=""><input class="form-check-input" type="checkbox" data-row="'+r.id+'" aria-label="Select '+r.id+'" '+(selected.has(r.id)?'checked':'')+'></td><td class=""><strong class="sv-num">'+r.id+'</strong></td><td class=""><strong class="">'+esc(r.customer)+'</strong><small class="">'+esc(r.email)+'</small></td><td class="">'+r.owner+'</td><td class=""><span class="sv-tag '+r.status.toLowerCase()+'">'+r.status+'</span></td><td class=" sv-num">$'+r.total.toFixed(2)+'</td></tr>').join('')||'<tr><td colspan="6" class="sv-empty">No matching orders. Clear the search or change your filters.</td></tr>';$('#sv-page-count').textContent=rows.length?'Showing '+(page*size+1)+'–'+Math.min(page*size+size,rows.length)+' of '+rows.length+' orders':'0 orders';$('#sv-prev').disabled=page===0;$('#sv-next').disabled=(page+1)*size>=rows.length;$('#sv-all').disabled=!visible.length;$('#sv-all').checked=visible.length>0&&visible.every(r=>selected.has(r.id));$('#sv-all').indeterminate=visible.some(r=>selected.has(r.id))&&!$('#sv-all').checked;$('#sv-bulk').hidden=selected.size===0;$('#sv-selected').textContent=selected.size+' order'+(selected.size===1?'':'s')+' selected';$$('[data-sort]').forEach(b=>{const th=b.closest('th');if(b.dataset.sort===sort)th.setAttribute('aria-sort',ascending?'ascending':'descending');else th.removeAttribute('aria-sort');});$$('[data-row]').forEach(c=>c.onchange=()=>{c.checked?selected.add(c.dataset.row):selected.delete(c.dataset.row);render()});}
function filtersChanged(){selected.clear();page=0;$('#sv-view').selectedIndex=-1;$('#sv-delete').disabled=true;render();}['sv-search','sv-state','sv-owner'].forEach(id=>$('#'+id).addEventListener('input',filtersChanged));$('#sv-page-size').onchange=()=>{page=0;render()};$$('[data-sort]').forEach(b=>b.onclick=()=>{ascending=b.dataset.sort===sort?!ascending:true;sort=b.dataset.sort;render()});$('#sv-prev').onclick=()=>{page--;render()};$('#sv-next').onclick=()=>{page++;render()};$('#sv-all').onchange=()=>{const size=+$('#sv-page-size').value;filtered().slice(page*size,page*size+size).forEach(r=>$('#sv-all').checked?selected.add(r.id):selected.delete(r.id));render()};$('#sv-clear').onclick=()=>{selected.clear();render();say('Selection cleared.')};function bulk(status){const n=selected.size;records.forEach(r=>{if(selected.has(r.id))r.status=status});selected.clear();const saved=persist();render();say(n+' orders moved to '+status+'.'+(saved?' Saved in this browser.':' Changes last for this tab only.'));}$('#sv-ready').onclick=()=>bulk('Ready');$('#sv-archive').onclick=()=>bulk('Archived');$('#sv-view').onchange=()=>{const v=views.find(v=>v.name===$('#sv-view').value);if(!v)return;$('#sv-search').value=v.query;$('#sv-state').value=v.status;$('#sv-owner').value=v.owner;$('#sv-page-size').value=v.size;sort=v.sort;ascending=v.ascending;page=0;selected.clear();$('#sv-delete').disabled=defaults.some(d=>d.name===v.name);render();say(v.name+' view applied.')};$('#sv-save').onclick=()=>{$('#sv-error').textContent='';$('#sv-view-name').value='';$('#sv-dialog').showModal()};$('#sv-cancel').onclick=()=>$('#sv-dialog').close();$('#sv-view-form').onsubmit=e=>{e.preventDefault();if(!e.currentTarget.reportValidity())return;const name=$('#sv-view-name').value.trim();if(!name){$('#sv-error').textContent='Enter a view name.';return;}if(views.some(v=>v.name.toLowerCase()===name.toLowerCase())){$('#sv-error').textContent='Choose a different name; this view already exists.';return;}views.push({name,...state()});const saved=persist();viewOptions(name);$('#sv-dialog').close();say(saved?'View saved in this browser.':'View created for this tab only.');};$('#sv-delete').onclick=()=>{const name=$('#sv-view').value;if(defaults.some(v=>v.name===name))return;views=views.filter(v=>v.name!==name);persist();viewOptions();$('#sv-view').dispatchEvent(new Event('change'));say('Custom view deleted. Default views remain available.')};$('#sv-export').onclick=()=>{const cell=x=>'"'+String(x).replace(/^[=+@-]/,"'$&").replaceAll('"','""')+'"';const text='\uFEFF'+[['Order','Customer','Email','Owner','Status','Total'],...filtered().map(r=>[r.id,r.customer,r.email,r.owner,r.status,r.total.toFixed(2)])].map(row=>row.map(cell).join(',')).join('\r\n');const url=URL.createObjectURL(new Blob([text],{type:'text/csv;charset=utf-8'}));const a=document.createElement('a');a.href=url;a.download='filtered-orders.csv';a.click();setTimeout(()=>URL.revokeObjectURL(url),1000);say('Filtered orders exported as CSV.')};viewOptions();render();})();

Tailwind 4 code

Requires: Tailwind CSS 4

HTML
<section id="saved-view-table" class="w-full overflow-hidden rounded-xl border border-[#d9dfea] bg-white font-sans text-[13px] leading-[1.5] text-[#1d293b] [&_button]:cursor-pointer [&_button:disabled]:cursor-not-allowed [&_button:disabled]:opacity-50 [&_button:focus-visible]:outline-3 [&_button:focus-visible]:outline-offset-2 [&_button:focus-visible]:outline-[#4338a2] [&_input:focus-visible]:outline-3 [&_input:focus-visible]:outline-offset-2 [&_input:focus-visible]:outline-[#4338a2] [&_select:focus-visible]:outline-3 [&_select:focus-visible]:outline-offset-2 [&_select:focus-visible]:outline-[#4338a2] [&_[tabindex]:focus-visible]:outline-3 [&_[tabindex]:focus-visible]:outline-offset-[-3px] [&_[tabindex]:focus-visible]:outline-[#4338a2]" aria-labelledby="sv-title">
 <header class="flex flex-col items-start justify-between gap-4 p-[18px] sm:flex-row sm:items-center sm:p-6"><div><p class="mb-2 text-[10px] font-bold tracking-[1.7px] text-[#4338a2]">FIELDWORK / ORDER OPERATIONS</p><h2 class="m-0 text-xl leading-normal font-bold tracking-[-.5px]" id="sv-title">A view for every workflow.</h2><p class="mt-1 text-xs text-[#526176]">Filter the work. Save your view. Move the right orders forward.</p></div><div class="flex flex-wrap items-center gap-2"><button type="button" class="inline-flex min-h-9 items-center justify-center gap-[5px] rounded-md border border-[#97a3b6] bg-white px-3 py-2 text-xs leading-normal font-semibold whitespace-nowrap text-[#1d293b]" id="sv-export" >Export CSV</button><button type="button" class="inline-flex min-h-9 items-center justify-center rounded-md border border-[#4338a2] bg-[#4338a2] px-3 py-2 text-xs leading-normal font-semibold text-white" id="sv-save" >Save this view</button></div></header>
 <div class="flex flex-wrap items-end gap-3 border-y border-[#d9dfea] bg-[#f8f9fc] p-4 sm:px-6"><div class="min-w-[120px] flex-1"><label class="mb-[5px] block text-[11px] font-semibold" for="sv-view">Saved view</label><select class="block h-[38px] w-full rounded-md border border-[#97a3b6] bg-white px-2.5 py-[7px] text-[13px] leading-normal text-[#1d293b]" id="sv-view"><option>All orders</option><option>Needs review</option></select></div><div class="min-w-[180px] flex-[2] basis-full sm:basis-auto"><label class="mb-[5px] block text-[11px] font-semibold" for="sv-search">Search orders</label><input class="block h-[38px] w-full rounded-md border border-[#97a3b6] bg-white px-2.5 py-[7px] text-[13px] leading-normal text-[#1d293b]" id="sv-search" type="search" placeholder="Order, customer or email"></div><div class="min-w-[120px] flex-1"><label class="mb-[5px] block text-[11px] font-semibold" for="sv-state">Status</label><select class="block h-[38px] w-full rounded-md border border-[#97a3b6] bg-white px-2.5 py-[7px] text-[13px] leading-normal text-[#1d293b]" id="sv-state"><option>All statuses</option><option>Review</option><option>Ready</option><option>Archived</option></select></div><div class="min-w-[120px] flex-1"><label class="mb-[5px] block text-[11px] font-semibold" for="sv-owner">Owner</label><select class="block h-[38px] w-full rounded-md border border-[#97a3b6] bg-white px-2.5 py-[7px] text-[13px] leading-normal text-[#1d293b]" id="sv-owner"><option>All owners</option><option>Mira</option><option>James</option><option>Avery</option></select></div><button type="button" class="inline-flex min-h-9 items-center justify-center gap-[5px] rounded-md border border-[#97a3b6] bg-white px-3 py-2 text-xs leading-normal font-semibold whitespace-nowrap text-[#1d293b]" id="sv-delete" disabled>Delete view</button></div>
 <div class="flex flex-wrap items-center gap-3 bg-[#eeecfb] px-4 py-3 hidden:hidden sm:px-6" id="sv-bulk" hidden><span class="mr-auto text-xs font-semibold" id="sv-selected"></span><button type="button" class="inline-flex min-h-9 items-center justify-center gap-[5px] rounded-md border border-[#97a3b6] bg-white px-3 py-2 text-xs leading-normal font-semibold whitespace-nowrap text-[#1d293b]" id="sv-ready" >Mark ready</button><button type="button" class="inline-flex min-h-9 items-center justify-center gap-[5px] rounded-md border border-[#97a3b6] bg-white px-3 py-2 text-xs leading-normal font-semibold whitespace-nowrap text-[#1d293b]" id="sv-archive" >Archive selected</button><button type="button" class="inline-flex min-h-9 items-center justify-center gap-[5px] rounded-md border border-[#97a3b6] bg-white px-3 py-2 text-xs leading-normal font-semibold whitespace-nowrap text-[#1d293b]" id="sv-clear" >Clear selection</button></div>
 <div class="max-w-full overflow-auto" tabindex="0" role="region" aria-label="Scrollable orders table"><table class="m-0 w-full border-collapse text-left font-sans text-xs leading-[1.5] [&_th]:border-b [&_th]:border-[#d9dfea] [&_th]:px-[14px] [&_th]:py-[15px] [&_th]:text-[10px] [&_th]:font-semibold [&_th]:tracking-[.6px] [&_th]:whitespace-nowrap [&_th]:text-[#526176] [&_th]:uppercase [&_th:first-child]:w-[42px] [&_th:first-child]:pr-0 sm:[&_th]:px-5 [&_th_button]:border-0 [&_th_button]:bg-transparent [&_th_button]:p-0 [&_th_button]:text-[inherit] [&_th_button]:font-[inherit] [&_th_button]:tracking-[inherit] [&_th_button]:uppercase"><caption class="sr-only">Orders with saved filters, sorting, page selection and bulk status actions</caption><thead><tr><th scope="col"><input class="h-4 w-4 accent-[#4338a2]" type="checkbox" id="sv-all" aria-label="Select all orders on this page"></th><th scope="col" id="sv-sort-id" aria-sort="ascending"><button type="button" data-sort="id">Order ↕</button></th><th scope="col">Customer</th><th scope="col">Owner</th><th scope="col">Status</th><th scope="col" id="sv-sort-total"><button type="button" data-sort="total">Total ↕</button></th></tr></thead><tbody id="sv-rows"></tbody></table></div>
 <div class="flex flex-wrap items-center justify-between gap-3 px-4 py-[17px] sm:px-6"><p class="text-[11px] text-[#526176]" id="sv-page-count"></p><div class="flex flex-wrap items-center gap-2"><label class="mb-[5px] block text-[11px] font-semibold" for="sv-page-size">Rows per page</label><select class="block h-[38px] w-full rounded-md border border-[#97a3b6] bg-white px-2.5 py-[7px] text-[13px] leading-normal text-[#1d293b]" style="width:auto" id="sv-page-size"><option>4</option><option>8</option><option>12</option></select><button type="button" class="inline-flex min-h-9 items-center justify-center gap-[5px] rounded-md border border-[#97a3b6] bg-white px-3 py-2 text-xs leading-normal font-semibold whitespace-nowrap text-[#1d293b]" id="sv-prev" >Previous</button><button type="button" class="inline-flex min-h-9 items-center justify-center gap-[5px] rounded-md border border-[#97a3b6] bg-white px-3 py-2 text-xs leading-normal font-semibold whitespace-nowrap text-[#1d293b]" id="sv-next" >Next</button></div></div><p class="px-4 pb-[18px] text-[11px] text-[#526176] sm:px-6">Selection spans pages of the current filter. Changing a filter clears selection. Views and demo changes save in this browser.</p><p class="px-4 pb-[18px] text-xs text-[#4338a2] empty:hidden sm:px-6" id="sv-status" role="status" aria-live="polite"></p>
 <dialog class="m-auto w-[min(430px,calc(100%-30px))] max-w-none rounded-xl border border-[#d9dfea] bg-white p-6 text-[#1d293b] backdrop:bg-[#17243b80]" id="sv-dialog" aria-labelledby="sv-dialog-title"><h3 class="text-lg font-bold" id="sv-dialog-title">Save this view</h3><p class="mt-1 text-xs text-[#526176]">Remember the current search, status, owner, sort and page size.</p><form id="sv-view-form"><div class="my-[18px]"><label class="mb-[5px] block text-[11px] font-semibold" for="sv-view-name">View name</label><input class="block h-[38px] w-full rounded-md border border-[#97a3b6] bg-white px-2.5 py-[7px] text-[13px] leading-normal text-[#1d293b]" type="text" id="sv-view-name" required maxlength="40" placeholder="Mira’s review queue"></div><p class="px-4 pb-[18px] text-xs text-[#4338a2] empty:hidden sm:px-6" id="sv-error" role="alert"></p><div class="flex flex-wrap items-center gap-2"><button class="inline-flex min-h-9 items-center justify-center rounded-md border border-[#4338a2] bg-[#4338a2] px-3 py-2 text-xs leading-normal font-semibold text-white" type="submit">Save view</button><button type="button" class="inline-flex min-h-9 items-center justify-center gap-[5px] rounded-md border border-[#97a3b6] bg-white px-3 py-2 text-xs leading-normal font-semibold whitespace-nowrap text-[#1d293b]" id="sv-cancel" >Cancel</button></div></form></dialog>
</section>
JavaScript
(()=>{'use strict';const root=document.querySelector('#saved-view-table');if(!root)return;const $=s=>root.querySelector(s),$$=s=>[...root.querySelectorAll(s)];const KEY='uic-table-saved-views-23';const esc=s=>String(s).replace(/[&<>"']/g,c=>({'&':'&','<':'<','>':'>','"':'"',"'":'''}[c]));const initial=[{"id":"ORD-1082","customer":"Hana Kim","email":"[email protected]","owner":"Mira","status":"Review","total":280},{"id":"ORD-1083","customer":"Leo Bennett","email":"[email protected]","owner":"James","status":"Ready","total":145},{"id":"ORD-1084","customer":"Amara Okafor","email":"[email protected]","owner":"Mira","status":"Review","total":620},{"id":"ORD-1085","customer":"Nora Ellis","email":"[email protected]","owner":"Avery","status":"Ready","total":96},{"id":"ORD-1086","customer":"Priya Shah","email":"[email protected]","owner":"James","status":"Review","total":340},{"id":"ORD-1087","customer":"Ravi Kapoor","email":"[email protected]","owner":"Mira","status":"Ready","total":192},{"id":"ORD-1088","customer":"Sofia Reyes","email":"[email protected]","owner":"Avery","status":"Review","total":455},{"id":"ORD-1089","customer":"Omar Haddad","email":"[email protected]","owner":"James","status":"Ready","total":85},{"id":"ORD-1090","customer":"Clara Dubois","email":"[email protected]","owner":"Mira","status":"Review","total":760},{"id":"ORD-1091","customer":"Theo Walsh","email":"[email protected]","owner":"Avery","status":"Ready","total":120},{"id":"ORD-1092","customer":"Mei Tan","email":"[email protected]","owner":"James","status":"Review","total":215},{"id":"ORD-1093","customer":"Kai Osei","email":"[email protected]","owner":"Mira","status":"Ready","total":410}];const defaults=[{name:'All orders',query:'',status:'All statuses',owner:'All owners',sort:'id',ascending:true,size:4},{name:'Needs review',query:'',status:'Review',owner:'All owners',sort:'id',ascending:true,size:4}];let records=structuredClone(initial),views=structuredClone(defaults);try{const saved=JSON.parse(localStorage.getItem(KEY));if(saved&&Array.isArray(saved.records)&&Array.isArray(saved.views)){records=saved.records;views=[...defaults,...saved.views.filter(v=>!defaults.some(d=>d.name===v.name))];}}catch{}let selected=new Set(),page=0,sort='id',ascending=true;const say=s=>$('#sv-status').textContent=s;const persist=()=>{try{localStorage.setItem(KEY,JSON.stringify({records,views:views.slice(2)}));return true;}catch{say('Browser storage is unavailable. Changes last for this tab only.');return false;}};const state=()=>({query:$('#sv-search').value,status:$('#sv-state').value,owner:$('#sv-owner').value,sort,ascending,size:+$('#sv-page-size').value});const filtered=()=>records.filter(r=>(r.id+' '+r.customer+' '+r.email).toLowerCase().includes($('#sv-search').value.toLowerCase())&&($('#sv-state').value==='All statuses'||r.status===$('#sv-state').value)&&($('#sv-owner').value==='All owners'||r.owner===$('#sv-owner').value)).sort((a,b)=>(sort==='total'?a.total-b.total:a.id.localeCompare(b.id))*(ascending?1:-1));function viewOptions(value='All orders'){$('#sv-view').innerHTML=views.map(v=>'<option>'+esc(v.name)+'</option>').join('');$('#sv-view').value=value;$('#sv-delete').disabled=!views.slice(2).some(v=>v.name===value);}function render(){const rows=filtered(),size=+$('#sv-page-size').value;page=Math.min(page,Math.max(0,Math.ceil(rows.length/size)-1));const visible=rows.slice(page*size,page*size+size);$('#sv-rows').innerHTML=visible.map(r=>'<tr class="data-[selected=true]:bg-[#f2f0fc]" data-selected="'+selected.has(r.id)+'"><td class="w-[42px] border-b border-[#d9dfea] px-[14px] py-[15px] pr-0 sm:pl-5"><input class="h-4 w-4 accent-[#4338a2]" type="checkbox" data-row="'+r.id+'" aria-label="Select '+r.id+'" '+(selected.has(r.id)?'checked':'')+'></td><td class="border-b border-[#d9dfea] px-[14px] py-[15px] align-middle whitespace-nowrap sm:px-5"><strong class="block font-semibold font-mono">'+r.id+'</strong></td><td class="border-b border-[#d9dfea] px-[14px] py-[15px] align-middle whitespace-nowrap sm:px-5"><strong class="block font-semibold">'+esc(r.customer)+'</strong><small class="block text-[10px] text-[#526176]">'+esc(r.email)+'</small></td><td class="border-b border-[#d9dfea] px-[14px] py-[15px] align-middle whitespace-nowrap sm:px-5">'+r.owner+'</td><td class="border-b border-[#d9dfea] px-[14px] py-[15px] align-middle whitespace-nowrap sm:px-5"><span class="inline-flex rounded-[5px] px-2 py-1 text-[10px] font-semibold '+(r.status==='Ready'?'bg-[#e3f3e9] text-[#186344]':r.status==='Review'?'bg-[#fff0d5] text-[#7b4911]':'bg-[#f0f2f6] text-[#445166]')+'">'+r.status+'</span></td><td class="border-b border-[#d9dfea] px-[14px] py-[15px] align-middle whitespace-nowrap sm:px-5 font-mono tabular-nums">$'+r.total.toFixed(2)+'</td></tr>').join('')||'<tr><td colspan="6" class="p-8 text-center text-[#526176]">No matching orders. Clear the search or change your filters.</td></tr>';$('#sv-page-count').textContent=rows.length?'Showing '+(page*size+1)+'–'+Math.min(page*size+size,rows.length)+' of '+rows.length+' orders':'0 orders';$('#sv-prev').disabled=page===0;$('#sv-next').disabled=(page+1)*size>=rows.length;$('#sv-all').disabled=!visible.length;$('#sv-all').checked=visible.length>0&&visible.every(r=>selected.has(r.id));$('#sv-all').indeterminate=visible.some(r=>selected.has(r.id))&&!$('#sv-all').checked;$('#sv-bulk').hidden=selected.size===0;$('#sv-selected').textContent=selected.size+' order'+(selected.size===1?'':'s')+' selected';$$('[data-sort]').forEach(b=>{const th=b.closest('th');if(b.dataset.sort===sort)th.setAttribute('aria-sort',ascending?'ascending':'descending');else th.removeAttribute('aria-sort');});$$('[data-row]').forEach(c=>c.onchange=()=>{c.checked?selected.add(c.dataset.row):selected.delete(c.dataset.row);render()});}
function filtersChanged(){selected.clear();page=0;$('#sv-view').selectedIndex=-1;$('#sv-delete').disabled=true;render();}['sv-search','sv-state','sv-owner'].forEach(id=>$('#'+id).addEventListener('input',filtersChanged));$('#sv-page-size').onchange=()=>{page=0;render()};$$('[data-sort]').forEach(b=>b.onclick=()=>{ascending=b.dataset.sort===sort?!ascending:true;sort=b.dataset.sort;render()});$('#sv-prev').onclick=()=>{page--;render()};$('#sv-next').onclick=()=>{page++;render()};$('#sv-all').onchange=()=>{const size=+$('#sv-page-size').value;filtered().slice(page*size,page*size+size).forEach(r=>$('#sv-all').checked?selected.add(r.id):selected.delete(r.id));render()};$('#sv-clear').onclick=()=>{selected.clear();render();say('Selection cleared.')};function bulk(status){const n=selected.size;records.forEach(r=>{if(selected.has(r.id))r.status=status});selected.clear();const saved=persist();render();say(n+' orders moved to '+status+'.'+(saved?' Saved in this browser.':' Changes last for this tab only.'));}$('#sv-ready').onclick=()=>bulk('Ready');$('#sv-archive').onclick=()=>bulk('Archived');$('#sv-view').onchange=()=>{const v=views.find(v=>v.name===$('#sv-view').value);if(!v)return;$('#sv-search').value=v.query;$('#sv-state').value=v.status;$('#sv-owner').value=v.owner;$('#sv-page-size').value=v.size;sort=v.sort;ascending=v.ascending;page=0;selected.clear();$('#sv-delete').disabled=defaults.some(d=>d.name===v.name);render();say(v.name+' view applied.')};$('#sv-save').onclick=()=>{$('#sv-error').textContent='';$('#sv-view-name').value='';$('#sv-dialog').showModal()};$('#sv-cancel').onclick=()=>$('#sv-dialog').close();$('#sv-view-form').onsubmit=e=>{e.preventDefault();if(!e.currentTarget.reportValidity())return;const name=$('#sv-view-name').value.trim();if(!name){$('#sv-error').textContent='Enter a view name.';return;}if(views.some(v=>v.name.toLowerCase()===name.toLowerCase())){$('#sv-error').textContent='Choose a different name; this view already exists.';return;}views.push({name,...state()});const saved=persist();viewOptions(name);$('#sv-dialog').close();say(saved?'View saved in this browser.':'View created for this tab only.');};$('#sv-delete').onclick=()=>{const name=$('#sv-view').value;if(defaults.some(v=>v.name===name))return;views=views.filter(v=>v.name!==name);persist();viewOptions();$('#sv-view').dispatchEvent(new Event('change'));say('Custom view deleted. Default views remain available.')};$('#sv-export').onclick=()=>{const cell=x=>'"'+String(x).replace(/^[=+@-]/,"'$&").replaceAll('"','""')+'"';const text='\uFEFF'+[['Order','Customer','Email','Owner','Status','Total'],...filtered().map(r=>[r.id,r.customer,r.email,r.owner,r.status,r.total.toFixed(2)])].map(row=>row.map(cell).join(',')).join('\r\n');const url=URL.createObjectURL(new Blob([text],{type:'text/csv;charset=utf-8'}));const a=document.createElement('a');a.href=url;a.download='filtered-orders.csv';a.click();setTimeout(()=>URL.revokeObjectURL(url),1000);say('Filtered orders exported as CSV.')};viewOptions();render();})();

About this set

A complete order workspace that joins saved filters, sorting, page selection and bulk status changes in one table. Start with All orders or Needs review, search by customer, email or order number, and narrow the list by status and owner. Save this view remembers those filters together with the sort direction and page size under a custom name. Custom views and demo order changes survive a reload in this browser. Checkbox selection can span several pages of the same filtered list; changing a filter clears it so hidden selections cannot be updated by accident. The page checkbox exposes an indeterminate state when only some visible rows are selected. Mark ready and Archive selected update the chosen orders, and archived orders remain available through the status filter. Export CSV downloads every matching row, rather than just the current page. Use this pattern for internal order desks and admin lists that repeat the same searches each day. Replace localStorage and the demo array with your API for shared records.

What’s included

  • Named views remember filters, sorting and page size
  • Selection across pages of the current filter
  • Indeterminate select-page checkbox and selection count
  • Bulk ready/archive actions with reversible status filtering
  • CSV export of the complete filtered result
  • Browser-local persistence with a session-only fallback

Accessibility

The table has a caption, column headers, named checkboxes and aria-sort on the sorted column. All controls use native inputs, selects and buttons; the save-view form uses a labelled native dialog with Escape support. Keyboard focus is outlined, the horizontal scroll region is focusable, and status changes are announced through a polite live region. Nothing animates.

Customise it

Change the order array and owner/status options in the inline script. The plain CSS and Bootstrap versions use the --sv-accent, --sv-ink and --sv-line properties; the Tailwind version uses the matching color and spacing utilities directly in its markup.