Documents · Source State Specimen — Distinguish an actually empty dataset, no matches after filtering and a failed load, and offer only the recovery action appropriate to…
HTML for this example
Select the code and use your copy shortcut. Changes in this preview are temporary.
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Documents · Source State Specimen</title><style>:root{--bg:#f4f6fa;--ink:#202b43;--accent:#345bba;--line:#d6dce8;--wash:#eaf0ff;}*{box-sizing:border-box}body{margin:0;font:16px/1.5 Arial,Helvetica,sans-serif;color:var(--ink);background:var(--bg)}main{max-width:1120px;padding:24px;margin:auto}h1,h2,h3,p{margin:0}h1{font-size:clamp(26px,4vw,38px);line-height:1.15;letter-spacing:-.03em}h2{font-size:23px}h3{font-size:18px}header{margin-bottom:20px}header p{margin-top:8px}.eyebrow{text-transform:uppercase;letter-spacing:.13em;font-size:12px;font-weight:bold;color:var(--accent)}button,input,select,textarea{font:inherit}button{cursor:pointer;min-height:44px;padding:9px 15px;border:1px solid var(--accent);background:var(--accent);color:white;border-radius:7px;font-weight:600}button.secondary{background:white;color:var(--accent)}button:disabled{opacity:.45;cursor:default}input,select,textarea{width:100%;min-height:44px;border:1px solid #a2aaba;border-radius:5px;background:white;color:var(--ink);padding:9px}textarea{resize:vertical;min-height:95px}label{display:block;font-size:14px;font-weight:bold;margin:12px 0 5px}input[type=checkbox]{width:20px;min-height:20px;vertical-align:middle;margin-right:8px}:focus-visible{outline:3px solid #df7a16;outline-offset:3px}.actions{display:flex;gap:9px;flex-wrap:wrap;margin:14px 0}.panel{padding:22px;background:white;border:1px solid var(--line);border-radius:12px;min-width:0}.columns{display:grid;grid-template-columns:1.6fr 1fr;gap:20px}.two{display:grid;grid-template-columns:1fr 1fr;gap:18px}.stats{display:flex;gap:12px;flex-wrap:wrap;margin-bottom:15px}.stat{flex:1;min-width:92px;background:var(--wash);padding:10px 14px;border-radius:8px}.stat small{display:block}.stat strong{font-size:25px}.muted{color:#526178;font-size:14px}.notice{padding:14px 16px;background:var(--wash);border-left:4px solid var(--accent);margin:14px 0;overflow-wrap:anywhere}.error{color:#a12e25;font-weight:bold}.below{margin-top:28px;padding-top:22px;border-top:1px solid var(--line)}.below p{margin-top:9px}svg.board{width:100%;display:block;border-radius:10px;border:1px solid var(--line)}table{border-collapse:collapse;width:100%;font-size:14px}td,th{text-align:left;padding:10px;border-bottom:1px solid var(--line);vertical-align:top;overflow-wrap:anywhere}th{font-size:12px;text-transform:uppercase;letter-spacing:.04em}pre{white-space:pre-wrap;overflow-wrap:anywhere;font:14px/1.6 ui-monospace,monospace}.scroll{overflow-x:auto}.tag{font-size:12px;padding:4px 8px;background:var(--wash);border-radius:4px}.big{font-size:clamp(36px,6vw,62px);font-weight:bold;line-height:1.15}.foot{font-size:14px;color:#526178;margin-top:25px}details{margin:18px 0}summary{cursor:pointer;font-weight:bold;min-height:44px;padding:10px 0}[hidden]{display:none!important}@media(max-width:800px){.columns{grid-template-columns:1fr}.two{grid-template-columns:1fr}}@media(max-width:480px){main{padding:18px 14px}.panel{padding:16px}.stat{min-width:78px;padding:8px}.actions button{flex-grow:1}td,th{padding:7px}.big{font-size:38px}}.workspace{background:#fff;border:1px solid var(--line);border-radius:12px;overflow:hidden}.toolbar{padding:18px 22px;border-bottom:1px solid var(--line);background:#f9faff}.workspace-title{display:flex;justify-content:space-between;align-items:center}.records{min-height:250px;padding:26px}.record{padding:18px;border-bottom:1px solid var(--line);display:flex;gap:15px;align-items:center}.file-icon{background:#ecf0fd;color:#345bba;border-radius:5px;padding:13px;font-size:18px}.empty{max-width:500px;margin:24px auto;text-align:center}.empty p{margin:10px 0}.state-title{font-size:26px}.counts{display:flex;gap:20px;font-size:14px;margin-top:14px}#resolve-box{background:#edf2fe;padding:16px;margin-top:14px}.trace-data{font:14px/1.7 ui-monospace,monospace;white-space:pre-wrap}</style></head><body><main><header><p class="eyebrow">Controlled local data specimen</p><h1>Documents</h1><p>Inspect results from a known source before deciding which recovery action helps.</p></header><div class="columns"><section class="workspace"><div class="toolbar"><div class="workspace-title"><h2>Reading desk</h2><span class="tag" id="source-status">F1 · Loaded</span></div><label for="query">Filter titles</label><input id="query" value="draft" placeholder="Search supplied records"><div class="counts"><span id="source-count">Source records: 2</span><span id="match-count">Matching records: 1</span></div></div><div class="records" id="result-region" aria-live="polite"><h3 id="display-state">Results</h3><p id="state-message"></p><div id="rows"></div><div class="actions"><button type="button" id="clear" class="secondary">Clear filter</button><button type="button" id="choose">Choose fixture</button><button type="button" id="retry">Retry fixture</button></div></div></section><aside class="panel"><h2>Source controls</h2><label for="fixture">Choose source fixture</label><select id="fixture"><option value="F1">Loaded F1 · two records</option><option value="F0">Loaded F0 · empty</option><option value="Loading">Loading · pending outcome</option><option value="Failed">Failed · count unknown</option></select><div id="resolve-box" hidden><label for="outcome">Manual fixture outcome</label><select id="outcome"><option value="">Choose an outcome</option value="F1">F1 · loaded two records</option><option value="F0">F0 · loaded empty</option><option value="Failed">Failed again</option></select><div class="actions"><button type="button" id="resolve">Resolve fixture outcome</button></div><p class="error" id="outcome-error" role="status"></p></div><div class="actions"><button type="button" id="reset" class="secondary">Reset demonstration</button></div><p class="muted">Retry is local and manual. No request is sent and no success is guaranteed.</p></aside></div><section class="below"><h2>Current state evidence</h2><pre class="trace-data" id="ledger"></pre><p class="foot">Fictional records R1 “Draft sketch” and R2 “Final outline”. Empty F0 means a known empty loaded source; Loading and Failed mean current records are unknown. No creation, saving, syncing or real network recovery is implemented. Titles are rendered as literal text.</p></section></main><script>'use strict';const $=id=>document.getElementById(id);const supplied=[{id:'R1',title:'Draft sketch'},{id:'R2',title:'Final outline'}];let source='F1',generation=0;
function model(){const q=$('query').value.trim().toLowerCase();if(source==='Loading'||source==='Failed')return {state:source==='Loading'?'Loading':'LoadError',data:null,matches:null};const data=source==='F1'?supplied:[];const matches=data.filter(r=>r.title.toLowerCase().includes(q));return {state:!data.length?'NoRecords':matches.length?'Results':'NoMatches',data,matches};}
function selectSource(next){if(!['F1','F0','Loading','Failed'].includes(next))return;generation++;source=next;$('fixture').value=next;$('outcome').value='';$('outcome-error').textContent='';render();}
function resolve(){if(source!=='Loading')return;const choice=$('outcome').value;if(!['F1','F0','Failed'].includes(choice)){$('outcome-error').textContent='Choose F1, F0 or Failed before resolving.';return;}selectSource(choice);}
function render(){const r=model();$('source-status').textContent=source+' · '+(r.data?'Loaded':source);$('source-count').textContent='Source records: '+(r.data?r.data.length:'Unknown');$('match-count').textContent='Matching records: '+(r.matches?r.matches.length:'Unknown');$('display-state').textContent=r.state;$('state-message').textContent=r.state==='Results'?'Supplied records matching your filter.':r.state==='NoMatches'?'No matches for “'+$('query').value.trim()+'”.':r.state==='NoRecords'?'No records supplied in this fixture.':r.state==='Loading'?'Loading fixture outcome; wait for explicit resolution.':'Could not load source. Current record count is unknown.';$('rows').textContent='';if(r.state==='Results'){for(const record of r.matches){const row=document.createElement('div');row.className='record';const icon=document.createElement('span');icon.className='file-icon';icon.textContent='▤';const text=document.createElement('span');text.textContent=record.id+' · '+record.title;row.append(icon,text);$('rows').append(row);}}$('clear').hidden=r.state!=='NoMatches'&&!(r.state==='Results'&&$('query').value.trim());$('choose').hidden=r.state!=='NoRecords';$('retry').hidden=r.state!=='LoadError';$('resolve-box').hidden=r.state!=='Loading';$('resolve').disabled=r.state!=='Loading';$('ledger').textContent='Source generation: '+generation+'\nSource fixture/status: '+source+'\nQuery retained: '+JSON.stringify($('query').value)+'\nDisplay state: '+r.state+'\nKnown source count: '+(r.data?r.data.length:'Unknown')+'\nKnown matching count: '+(r.matches?r.matches.length:'Unknown')+'\nRecovery: '+(r.state==='NoMatches'?'Clear filter':r.state==='NoRecords'?'Choose fixture':r.state==='LoadError'?'Retry fixture':r.state==='Loading'?'Choose then resolve an outcome':'Filter current source');}
$('query').addEventListener('input',render);$('fixture').addEventListener('change',()=>selectSource($('fixture').value));$('clear').addEventListener('click',()=>{$('query').value='';render();});$('choose').addEventListener('click',()=>$('fixture').focus());$('retry').addEventListener('click',()=>{if(source==='Failed')selectSource('Loading');});$('resolve').addEventListener('click',resolve);$('reset').addEventListener('click',()=>{$('query').value='draft';selectSource('F1');});globalThis.app={model,selectSource,resolve,get:()=>({source,generation})};render();</script></body></html>