Cards, Lists, and Content Organization

Reading List Bookmark Organizer

Complete the bookmark organizer for a reading list scenario: includes realistic content, actionable controls, clear status feedback, and responsive layouts across sizes.

Cards, Lists, and Content OrganizationBookmark OrganizerHTMLCSS GridJavaScript
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>Reading List Bookmark Organizer</title>
  <style>
    :root { --ink:#24213a; --paper:#f6f1e8; --accent:#e6a23c; --secondary:#a8a1d8; --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:Optima,"Songti SC",serif; background:radial-gradient(ellipse at top left,color-mix(in srgb,var(--secondary) 32%,transparent),transparent 42%),radial-gradient(ellipse at bottom right,color-mix(in srgb,var(--accent) 18%,transparent),transparent 45%),var(--paper); }
    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(1100px,calc(100% - 34px));margin:auto;padding:68px 0}.mast{display:grid;grid-template-columns:1fr auto;align-items:center;gap:40px;margin:0 4vw 36px}.mast h1{font-family:Optima,"Songti SC",serif;font-weight:700;font-size:clamp(40px,8vw,86px);letter-spacing:-.025em;margin:0;line-height:1.02}.eyebrow{display:block;margin-bottom:12px;color:var(--accent);font-size:12px;letter-spacing:.2em}.intro{max-width:60ch;line-height:1.9}.scenario{display:grid;width:108px;height:108px;place-items:center;padding:12px;border:1px solid var(--line);border-radius:50%;text-align:center}.demo{border-radius:72px 18px 72px 18px;box-shadow:0 28px 80px color-mix(in srgb,var(--ink) 14%,transparent);position:relative;min-height:430px;overflow:hidden;padding:clamp(28px,5vw,58px);background:color-mix(in srgb,var(--paper) 84%,transparent)}@media(max-width:700px){.page{width:calc(100% - 18px);padding:24px 0}.mast{grid-template-columns:1fr;margin-inline:12px}.scenario{width:auto;height:auto;border-radius:999px}.demo{padding:18px}}
    .panel{padding:26px;border:1px solid var(--line);border-radius:2px;background:var(--paper)}.stack{display:grid;gap:28px}.row{display:flex;gap:20px;flex-wrap:wrap}.action{padding:9px 2px;border:0;border-bottom:2px solid var(--line);background:transparent}.action.primary,.action.is-active{border-color:var(--accent);color:var(--accent)}.muted{font-size:14px;line-height:1.9}.status{min-height:20px;margin-top:28px;font-size:13px}.metric{font-size:clamp(40px,9vw,88px);font-weight:500;letter-spacing:-.06em}.meter{height:2px;background:var(--line)}.meter>i{display:block;height:100%;background:var(--accent)}.chip{font-size:11px;letter-spacing:.12em;text-transform:uppercase}
    .composition-deck{display:grid;grid-template-rows:auto 1fr;border:1px solid var(--line);border-radius:24px;overflow:hidden;background:color-mix(in srgb,var(--ink) 4%,var(--paper))}.deck-bar{display:flex;justify-content:space-between;gap:18px;align-items:center;padding:12px 18px;color:var(--paper);background:var(--ink);font:700 12px/1 ui-monospace,monospace}.deck-lights{display:flex;gap:7px}.deck-lights i{width:10px;height:10px;border-radius:50%;background:var(--accent)}.deck-lights i:nth-child(2){background:var(--secondary)}.deck-lights i:nth-child(3){background:color-mix(in srgb,var(--paper) 55%,transparent)}.composition-deck .demo{border:0;border-radius:0;box-shadow:none}
    .bookmark-demo{display:grid;grid-template-columns:220px 1fr;min-height:380px;border:1px solid var(--line);border-radius:18px;overflow:hidden;background:var(--paper)}.bookmark-demo aside{padding:20px;background:var(--ink);color:var(--paper)}.bookmark-demo aside h2{margin:.3em 0}.bookmark-demo nav{display:grid;gap:5px;margin-top:20px}.bookmark-demo nav button{display:flex;justify-content:space-between;padding:11px;border:0;border-radius:9px;color:inherit;background:transparent}.bookmark-demo nav button[aria-current="true"]{color:var(--ink);background:var(--secondary)}.bookmark-demo>section{display:grid;align-content:start;gap:14px;padding:22px}.bookmark-demo>section>label{display:flex;gap:10px;justify-content:flex-end}.bookmark-demo select{padding:8px;border:1px solid var(--line);border-radius:8px;background:var(--paper)}#bookmarkList{display:grid;gap:8px}#bookmarkList>label{display:grid;grid-template-columns:auto 1fr;gap:10px;align-items:center;padding:12px;border:1px solid var(--line);border-radius:11px}#bookmarkList>label>span{display:grid;gap:4px}@media(max-width:620px){.bookmark-demo{grid-template-columns:1fr}.bookmark-demo nav{grid-auto-flow:column;overflow:auto}}.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="organic" data-composition="control-deck">
  <main class="page">
    <header class="mast"><div><span class="eyebrow">organic / Bookmark Organizer / INTERMEDIATE</span><h1>Reading List Bookmark Organizer</h1><p class="intro">Complete the bookmark organizer for a reading list scenario: includes realistic content, actionable controls, clear status feedback, and responsive layouts across sizes.</p></div><span class="scenario">Reading List</span></header>
    <div class="composition-deck"><div class="deck-bar"><span>CONTROL DECK · 04</span><span>Bookmark Organizer</span><span class="deck-lights" aria-hidden="true"><i></i><i></i><i></i></span></div><section class="demo" aria-label="Reading List Bookmark Organizer Interactive Area"><div class="workflow-dispatch"><aside class="dispatch-console"><span class="eyebrow">Reading List DISPATCH</span><h2>Reading Queue Command Center</h2><form id="workflowDispatchForm"><label>Task Type<select id="workflowDispatchKind"><option>Reading List</option><option>In-depth feature</option><option>Excerpted and organized</option></select></label><label>Number to read<input id="workflowDispatchAmount" type="number" min="1" max="9999" value="42"><span>page</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">Arrange reading</button></form><label>Current task<select id="workflowDispatchActive" aria-label="Switch current task"><option value="1">Reading List</option><option value="2">In-depth feature</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:cards-lists-content-bookmark-organizer --><div class="bookmark-demo"><aside><span class="eyebrow">BOOKMARKS</span><h2>Reading List Bookmarks</h2><nav aria-label="Bookmark Folder"><button type="button" data-folder="0" aria-current="true">Read later<span>0</span></button><button type="button" data-folder="1">Work references<span>0</span></button><button type="button" data-folder="2">Inspiration bookmarks<span>0</span></button></nav></aside><section><label>Move selected bookmarks to <select id="bookmarkTarget" data-core-bridge="cards-lists-content-bookmark-organizer"><option value="0">Read later</option><option value="1">Work references</option><option value="2">Inspiration bookmarks</option></select><output id="bookmarkTargetSummary">Goal: read later</output></label><div id="bookmarkList"><label data-bookmark-folder="0"><input type="checkbox"><span><b>Reading List Plan</b><small>Local Saved Records</small></span></label><label data-bookmark-folder="1"><input type="checkbox"><span><b>Reading List Inspiration</b><small>Local Saved Records</small></span></label><label data-bookmark-folder="2"><input type="checkbox"><span><b>Reading List Records</b><small>Local Saved Records</small></span></label><label data-bookmark-folder="0"><input type="checkbox"><span><b>Reading List Collaboration</b><small>Local Saved Records</small></span></label><label data-bookmark-folder="1"><input type="checkbox"><span><b>Reading List Progress</b><small>Local Saved Records</small></span></label><label data-bookmark-folder="2"><input type="checkbox"><span><b>Reading List Reminder</b><small>Local Saved Records</small></span></label><label data-bookmark-folder="0"><input type="checkbox"><span><b>Reading List Favorites</b><small>Local Saved Records</small></span></label></div><button id="moveBookmarks" class="action primary" type="button">Move selected</button></section></div><!-- 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:cards-lists-content-bookmark-organizer */
let activeFolder=0;const folderButtons=[...document.querySelectorAll('[data-folder]')];const bookmarks=[...document.querySelectorAll('[data-bookmark-folder]')];const bookmarkTarget=document.querySelector('#bookmarkTarget');function renderBookmarkTarget(){const folder=folderButtons[Number(bookmarkTarget.value)].childNodes[0].textContent;document.querySelector('#bookmarkTargetSummary').textContent='Goal:'+folder;announce('The moving target has switched to '+folder);}function renderBookmarks(){bookmarks.forEach(bookmark=>{bookmark.hidden=Number(bookmark.dataset.bookmarkFolder)!==activeFolder;});folderButtons.forEach(button=>{button.querySelector('span').textContent=bookmarks.filter(bookmark=>Number(bookmark.dataset.bookmarkFolder)===Number(button.dataset.folder)).length;});announce('Current folder has '+bookmarks.filter(bookmark=>!bookmark.hidden).length+' bookmarks');}folderButtons.forEach(button=>button.addEventListener('click',()=>{activeFolder=Number(button.dataset.folder);folderButtons.forEach(item=>item.removeAttribute('aria-current'));button.setAttribute('aria-current','true');renderBookmarks();}));bookmarkTarget.addEventListener('change',renderBookmarkTarget);document.querySelector('#moveBookmarks').addEventListener('click',()=>{const target=Number(bookmarkTarget.value);const selected=bookmarks.filter(bookmark=>bookmark.querySelector('input').checked);selected.forEach(bookmark=>{bookmark.dataset.bookmarkFolder=target;bookmark.querySelector('input').checked=false;});renderBookmarks();announce('Moved '+selected.length+' Bookmark to-do '+folderButtons[target].childNodes[0].textContent);});renderBookmarks();renderBookmarkTarget();
/* 11DZ_CORE_SCRIPT_END */
const workflowBridgeSpec={"name":"cards-lists-content-bookmark-organizer","selector":"[data-core-bridge=\"cards-lists-content-bookmark-organizer\"]","mode":"select","key":"ArrowRight"};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.setAttribute('aria-keyshortcuts',workflowBridgeSpec.key);workflowBridgeControl.addEventListener('keydown',event=>{if(event.key!==workflowBridgeSpec.key)return;event.preventDefault();workflowBridgeControl.selectedIndex=(workflowBridgeControl.selectedIndex+1)%workflowBridgeControl.options.length;workflowBridgeControl.dispatchEvent(new Event('input',{bubbles:true}));workflowBridgeControl.dispatchEvent(new Event('change',{bubbles:true}));});workflowBridgeControl.addEventListener("keydown",workflowBridgeScheduleCommit);workflowBridgeControl.addEventListener('input',workflowBridgeScheduleCommit);workflowBridgeControl.addEventListener('change',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.selectedIndex=(workflowBridgeControl.selectedIndex+1)%workflowBridgeControl.options.length;workflowBridgeControl.dispatchEvent(new Event('change',{bubbles:true}));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":"Reading List","amount":12,"priority":"normal","touches":0}],["2",{"label":"In-depth feature","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+' p · '+bridge.summary;announce('Current task in reading 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+' p · '+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