Floating layers and status feedback

Document Review Side Drawer

Complete a side drawer for the document review scenario: includes real content, actionable controls, clear state feedback, and responsive layouts across sizes.

Floating layers and status feedbackSide drawerHTMLCSSJavaScript
With JavaScript enabled, you can edit, run, and save this example. The fixed source is as follows:
<!doctype html>
<html lang="en" dir="ltr">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Document Review Side Drawer</title>
  <style>
    :root { --ink:#ecf7f3; --paper:#071310; --accent:#ff6b5e; --secondary:#71c9b5; --line:color-mix(in srgb, var(--ink) 18%, transparent); --shadow:0 24px 60px color-mix(in srgb, var(--ink) 16%, transparent); color-scheme:light; }
    * { box-sizing:border-box; }
    html { min-width:320px; background:var(--paper); }
    body { min-height:100vh; margin:0; overflow-x:hidden; color:var(--ink); font-family:ui-monospace,"SFMono-Regular",Consolas,monospace; background:linear-gradient(color-mix(in srgb,var(--secondary) 5%,transparent) 1px,transparent 1px),linear-gradient(90deg,color-mix(in srgb,var(--secondary) 5%,transparent) 1px,transparent 1px),var(--paper);background-size:24px 24px; }
    button,input,select,textarea { color:inherit; font:inherit; }
    button,[role="button"],input,select,textarea { accent-color:var(--accent); }
    button { cursor:pointer; }
    button:focus-visible,input:focus-visible,select:focus-visible,textarea:focus-visible,[tabindex]:focus-visible { outline:3px solid var(--accent); outline-offset:3px; }
    [hidden] { display:none !important; }
    @media (max-width:700px) { .mast h1 { line-height:1.08 !important; letter-spacing:-.035em !important; overflow-wrap:anywhere; } }
    @media (prefers-reduced-motion:reduce) { *,*::before,*::after { scroll-behavior:auto !important; animation-duration:.01ms !important; animation-iteration-count:1 !important; transition-duration:.01ms !important; } }
    .page{width:min(1080px,calc(100% - 30px));margin:auto;padding:48px 0}.eyebrow{color:var(--secondary);font:700 12px/1.3 ui-monospace,monospace}.eyebrow::before{content:"> ";color:var(--accent)}.mast{display:grid;grid-template-columns:1fr auto;border:1px solid var(--secondary);padding:18px;gap:24px;align-items:center;margin-bottom:16px}.mast h1{font-family:ui-monospace,"SFMono-Regular",monospace;font-weight:700;font-size:clamp(34px,7vw,72px);letter-spacing:-.055em;margin:12px 0;line-height:1.05}.intro{margin:0;color:color-mix(in srgb,var(--ink) 72%,transparent);font:400 14px/1.7 ui-monospace,monospace}.scenario{padding:7px 10px;border:1px dashed var(--secondary);font:700 11px/1 ui-monospace,monospace}.demo{border-color:var(--secondary);border-radius:8px;box-shadow:0 0 50px color-mix(in srgb,var(--secondary) 15%,transparent);position:relative;min-height:390px;padding:26px;background:color-mix(in srgb,var(--paper) 94%,#000)}@media(max-width:700px){.page{width:calc(100% - 18px);padding:20px 0}.mast{grid-template-columns:1fr}.demo{padding:14px}}
    .stack{display:flex;flex-direction:column;gap:18px}.panel{padding:28px;border-left:7px solid var(--accent);background:color-mix(in srgb,var(--secondary) 12%,var(--paper))}.action{min-height:46px;padding:11px 18px;border:0;border-bottom:3px solid var(--ink);background:transparent;font-weight:900}.action.primary,.action.is-active{color:var(--paper);background:var(--ink)}.row{display:grid;grid-template-columns:repeat(auto-fit,minmax(120px,1fr));gap:8px}.metric{font:900 clamp(32px,7vw,64px)/1 ui-monospace,monospace}.status{min-height:22px;padding-top:12px;border-top:1px dashed var(--line)}.muted{color:color-mix(in srgb,var(--ink) 62%,transparent)}.chip{display:inline-block;padding:5px 8px;background:var(--secondary)}.meter{height:12px;border:1px solid var(--ink)}.meter>i{display:block;height:100%;background:var(--ink)}
    .composition-split{display:grid;grid-template-columns:150px minmax(0,1fr);gap:18px;align-items:start}.split-note{position:sticky;top:20px;display:grid;gap:14px;padding:18px 12px;border-block:3px double var(--accent);font-size:13px;line-height:1.65}.split-note b{font:900 12px/1 ui-monospace,monospace;letter-spacing:.12em}.split-note span{writing-mode:vertical-rl;min-height:120px;color:color-mix(in srgb,var(--ink) 60%,transparent)}.composition-split .demo{min-width:0}@media(max-width:900px){.composition-split{grid-template-columns:1fr}.split-note{position:static;grid-template-columns:auto 1fr}.split-note span{writing-mode:horizontal-tb;min-height:0}}
    .drawer-canvas{display:grid;gap:22px;min-height:380px;padding:clamp(24px,6vw,66px);border:1px solid var(--line);border-radius:30px;background:linear-gradient(130deg,var(--paper),color-mix(in srgb,var(--secondary) 18%,var(--paper)))}.drawer-canvas h2{margin:0;font-size:clamp(36px,8vw,82px)}.drawer-cards{display:grid;grid-template-columns:repeat(3,1fr);gap:10px}.drawer-cards article{display:grid;gap:7px;padding:16px;border:1px solid var(--line);border-radius:14px;background:var(--paper)}.drawer-canvas>.action{justify-self:start}.drawer-demo dialog{width:min(460px,calc(100% - 20px));height:calc(100dvh - 20px);max-height:none;margin:10px 10px 10px auto;padding:0;border:0;border-radius:26px;color:var(--ink);background:var(--paper);box-shadow:-24px 0 70px #0004}.drawer-demo dialog::backdrop{background:#1118}.drawer-demo form{display:grid;grid-template-rows:auto auto 1fr auto;height:100%}.drawer-demo form header,.drawer-demo form footer{display:flex;justify-content:space-between;gap:16px;align-items:center;padding:20px;border-bottom:1px solid var(--line)}.drawer-demo form header h2{margin:.2em 0}.drawer-demo form button{padding:10px 14px;border:1px solid var(--line);border-radius:9px;background:transparent}.drawer-demo form header>button{width:42px;height:42px;padding:0;border-radius:50%;font-size:22px}.drawer-demo nav{display:flex;gap:6px;padding:12px 20px;border-bottom:1px solid var(--line)}.drawer-demo nav button[aria-current="page"]{color:var(--paper);background:var(--ink)}.drawer-content{padding:28px;line-height:1.8}.drawer-content strong{font-size:30px}.drawer-demo form footer{border-top:1px solid var(--line);border-bottom:0}.drawer-demo form footer .primary{color:var(--paper);background:var(--accent)}@media(max-width:560px){.drawer-cards{grid-template-columns:1fr}.drawer-demo dialog{width:calc(100% - 12px);height:calc(100dvh - 12px);margin:6px}}.workflow-dispatch{display:grid;grid-template-columns:minmax(210px,.48fr) minmax(0,1.52fr);gap:18px}.dispatch-console{display:grid;align-content:start;gap:16px;padding:22px;border:1px solid var(--line);border-radius:18px;background:color-mix(in srgb,var(--secondary) 12%,var(--paper))}.dispatch-console h2{margin:.2em 0}.dispatch-console form,.dispatch-console label{display:grid;gap:7px}.dispatch-console input,.dispatch-console select{min-width:0;width:100%;padding:10px;border:1px solid var(--line);border-radius:8px;background:var(--paper)}.dispatch-console fieldset{display:flex;gap:12px;border:1px solid var(--line);border-radius:10px}.dispatch-console fieldset label{display:flex;align-items:center}.dispatch-workbench{--dispatch-load:.22;min-width:0;padding:14px;border-left:8px solid color-mix(in srgb,var(--accent) calc(var(--dispatch-load)*100%),var(--line));background:linear-gradient(90deg,color-mix(in srgb,var(--accent) 8%,transparent),transparent 28%)}.dispatch-workbench[data-dispatch-priority="urgent"]{box-shadow:inset 0 0 0 2px var(--accent)}@media(max-width:900px){.workflow-dispatch{grid-template-columns:1fr}.dispatch-console{order:2}}
  </style>
</head>
<body data-aesthetic="terminal" data-composition="split-note">
  <main class="page">
    <header class="mast"><div><span class="eyebrow">terminal / side drawer / ADVANCED</span><h1>Document Review Side Drawer</h1><p class="intro">Complete a side drawer for the document review scenario: includes real content, actionable controls, clear state feedback, and responsive layouts across sizes.</p></div><span class="scenario">Document Review</span></header>
    <div class="composition-split"><aside class="split-note"><b>CASE 02</b><span>Master the semantic structure, responsive layout, keyboard operation, and state synchronization of side drawers.</span></aside><section class="demo" aria-label="Document Review Side Drawer Interaction Area"><div class="workflow-dispatch"><aside class="dispatch-console"><span class="eyebrow">Document Review DISPATCH</span><h2>Review Queue Control Center</h2><form id="workflowDispatchForm"><label>Task Type<select id="workflowDispatchKind"><option>Text Editing</option><option>Structural Suggestions</option><option>Publish Confirmation</option></select></label><label>Pending reviews<input id="workflowDispatchAmount" type="number" min="1" max="9999" value="21"><span>item</span></label><fieldset><legend>Processing priority</legend><label><input type="radio" name="workflowPriority" value="normal" checked>Regular</label><label><input type="radio" name="workflowPriority" value="urgent">Urgent</label></fieldset><button class="action primary" type="submit">Submit for Review</button></form><label>Current task<select id="workflowDispatchActive" aria-label="Switch current task"><option value="1">Text Editing</option><option value="2">Structural Suggestions</option></select></label><output id="workflowDispatchSummary">Waiting for Dispatch</output></aside><section id="workflowCore" class="workflow-core dispatch-workbench" data-dispatch-priority="normal"><!-- 11DZ_CORE_START:overlays-feedback-side-drawer --><section class="drawer-demo"><div class="drawer-canvas"><span class="eyebrow">SIDE DRAWER</span><h2>Document review workspace</h2><div class="drawer-cards"><article><span>01</span><strong>Document Review Favorites</strong></article><article><span>02</span><strong>Document Review Overview</strong></article><article><span>03</span><strong>Document Review Plan</strong></article></div><button id="drawerOpen" class="action primary" type="button" aria-controls="sideDrawer" data-core-bridge="overlays-feedback-side-drawer">Open side details</button></div><dialog id="sideDrawer" aria-labelledby="drawerTitle"><form method="dialog"><header><div><span class="eyebrow">DETAIL PANEL</span><h2 id="drawerTitle">Document Review Favorites</h2></div><button value="close" aria-label="Close side details">×</button></header><nav aria-label="Detail Section"><button type="button" data-drawer-tab="0" aria-current="page">Overview</button><button type="button" data-drawer-tab="1">Record</button><button type="button" data-drawer-tab="2">Collaborator</button></nav><div id="drawerContent" class="drawer-content"><strong>Overview</strong><p>A side drawer keeps the main page context and fills the available width on narrow screens.</p></div><footer><button value="close">Handle later</button><button value="saved" class="primary">Save Details</button></footer></form></dialog></section><!-- 11DZ_CORE_END --></section></div><p id="status" class="status" role="status" aria-live="polite"></p></section></div>
  </main>
  <script>
    'use strict';
    const statusOutput = document.querySelector('#status');
    const announce = message => { statusOutput.textContent = message; };
    /* 11DZ_CORE_SCRIPT_START:overlays-feedback-side-drawer */
const sideDrawer=document.querySelector('#sideDrawer');document.querySelector('#drawerOpen').addEventListener('click',()=>{sideDrawer.returnValue='close';sideDrawer.showModal();});const drawerTabs=[...document.querySelectorAll('[data-drawer-tab]')];const drawerCopy=[['Overview','View the summary and main status of the current project.'],['Record','Review recent updates and handling results by time.'],['Collaborator','Confirm the participating members and the steps each is responsible for.']];drawerTabs.forEach((button,index)=>button.addEventListener('click',()=>{drawerTabs.forEach(item=>item.removeAttribute('aria-current'));button.setAttribute('aria-current','page');document.querySelector('#drawerContent').innerHTML='<strong>'+drawerCopy[index][0]+'</strong><p>'+drawerCopy[index][1]+'</p>';announce('Drawer switched to '+drawerCopy[index][0]);}));sideDrawer.addEventListener('click',event=>{if(event.target===sideDrawer)sideDrawer.close('close');});sideDrawer.addEventListener('close',()=>announce(sideDrawer.returnValue==='saved'?'Side details saved':'Side details closed'));
/* 11DZ_CORE_SCRIPT_END */
const workflowBridgeSpec={"name":"overlays-feedback-side-drawer","selector":"[data-core-bridge=\"overlays-feedback-side-drawer\"]","mode":"click","key":"Enter"};const workflowBridgeCore=document.querySelector('#workflowCore');const workflowBridgeControl=workflowBridgeCore.querySelector(workflowBridgeSpec.selector);if(!workflowBridgeControl)throw new Error('Missing core bridge: '+workflowBridgeSpec.name);const workflowBridgeControlledId=workflowBridgeControl.getAttribute('aria-controls');const workflowBridgeControlled=workflowBridgeControlledId?document.getElementById(workflowBridgeControlledId):null;workflowBridgeCore.dataset.workflowBridge=workflowBridgeSpec.name;workflowBridgeCore.dataset.workflowVersion='0';function workflowBridgeSerialize(){const visualNode=workflowBridgeCore.firstElementChild||workflowBridgeCore;const visual=getComputedStyle(visualNode);const outputs=[...workflowBridgeCore.querySelectorAll('output,[role="status"],[aria-live],meter,progress')].map(node=>node.textContent.trim()+'|'+node.getAttribute('aria-valuenow')+'|'+node.getAttribute('value'));const canvas=[...workflowBridgeCore.querySelectorAll('canvas')].map(node=>{try{return node.toDataURL().slice(-160);}catch{return 'canvas-unavailable';}});return JSON.stringify({html:workflowBridgeCore.innerHTML,status:statusOutput.textContent,outputs,canvas,visual:[visual.display,visual.visibility,visual.opacity,visual.transform,visual.filter,visual.backgroundColor,visual.width,visual.height],scroll:workflowBridgeSpec.mode==='scroll'?workflowBridgeControl.scrollTop:null});}let workflowBridgeLastEffect=workflowBridgeSerialize();function workflowBridgeSummary(){const label=(workflowBridgeControl.getAttribute('aria-label')||workflowBridgeControl.textContent||workflowBridgeControl.value||workflowBridgeSpec.name).trim().replace(/\s+/g,' ').slice(0,72);return label+' · Core Version '+workflowBridgeCore.dataset.workflowVersion;}function workflowBridgeCommit(){const effect=workflowBridgeSerialize();if(effect===workflowBridgeLastEffect)return {changed:false,summary:workflowBridgeSummary()};workflowBridgeLastEffect=effect;workflowBridgeCore.dataset.workflowVersion=String(Number(workflowBridgeCore.dataset.workflowVersion||0)+1);return {changed:true,summary:workflowBridgeSummary()};}function workflowBridgeScheduleCommit(){queueMicrotask(workflowBridgeCommit);setTimeout(workflowBridgeCommit,0);}workflowBridgeControl.addEventListener("click",workflowBridgeScheduleCommit);const workflowBridgeStateTargets=new Set(workflowBridgeCore.querySelectorAll('dialog'));if(workflowBridgeControlled&&workflowBridgeCore.contains(workflowBridgeControlled))workflowBridgeStateTargets.add(workflowBridgeControlled);workflowBridgeStateTargets.forEach(target=>['close','cancel','toggle'].forEach(eventName=>target.addEventListener(eventName,workflowBridgeScheduleCommit)));function workflowBridgeActivate(){workflowBridgeControl.focus();workflowBridgeControl.click();const result=workflowBridgeCommit();setTimeout(workflowBridgeCommit,0);return result;}function workflowBridgeReset(){workflowBridgeCore.dataset.workflowVersion='0';workflowBridgeLastEffect=workflowBridgeSerialize();}
const workflowDispatchCore=document.querySelector('#workflowCore');const workflowDispatchForm=document.querySelector('#workflowDispatchForm');const workflowDispatchSelect=document.querySelector('#workflowDispatchActive');const workflowDispatchJobs=new Map([["1",{"label":"Text Editing","amount":12,"priority":"normal","touches":0}],["2",{"label":"Structural Suggestions","amount":21,"priority":"urgent","touches":0}]]);let workflowDispatchSerial=workflowDispatchJobs.size;function workflowDispatchDrive(job,activate=false){workflowDispatchCore.dataset.dispatchPriority=job.priority;workflowDispatchCore.style.setProperty('--dispatch-load',Math.min(.95,.16+job.amount/120));const bridge=activate?workflowBridgeActivate():{changed:false,summary:workflowBridgeSummary()};document.querySelector('#workflowDispatchSummary').textContent=job.label+' · '+job.amount+' item · '+bridge.summary;announce('Current task in the review queue:'+job.label);}function workflowDispatchRender(activeId,activate=false){workflowDispatchSelect.replaceChildren(...[...workflowDispatchJobs].map(([id,job])=>{const option=document.createElement('option');option.value=id;option.textContent=job.label+(job.priority==='urgent'?' · Urgent':'');return option;}));workflowDispatchSelect.value=activeId;workflowDispatchDrive(workflowDispatchJobs.get(activeId),activate);}workflowDispatchForm.addEventListener('submit',event=>{event.preventDefault();const data=new FormData(workflowDispatchForm);const id=String(++workflowDispatchSerial);workflowDispatchJobs.set(id,{label:document.querySelector('#workflowDispatchKind').value,amount:Math.max(1,Number(document.querySelector('#workflowDispatchAmount').value)||1),priority:data.get('workflowPriority'),touches:0});workflowDispatchRender(id,true);});workflowDispatchSelect.addEventListener('change',()=>workflowDispatchDrive(workflowDispatchJobs.get(workflowDispatchSelect.value),true));workflowDispatchCore.addEventListener('focusin',()=>{const job=workflowDispatchJobs.get(workflowDispatchSelect.value);if(!job)return;job.touches+=1;document.querySelector('#workflowDispatchSummary').textContent=job.label+' · '+job.amount+' item · '+workflowBridgeSummary();});workflowDispatchRender('1',false);
workflowBridgeReset();
  </script>
</body>
</html>
Page feedbackFound an issue or have suggestions for improvement?
Feedback features need to be used in the online version

Please enable JavaScript in the online version before submitting; local features of the current tool or example are not affected.

Go to the online version for feedback