Basic Controls and Selectors

Loft lounge numeric stepper

Complete the numeric stepper in the loft lounge scene: includes real content, interactive controls, clear status feedback, and responsive layout across sizes.

Basic Controls and SelectorsNumeric StepperHTMLCSSJavaScript
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>Loft lounge numeric stepper</title>
  <style>
    :root { --ink:#102c44; --paper:#eef6f8; --accent:#e05263; --secondary:#79b7c7; --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:Baskerville,"Songti SC",serif; background:linear-gradient(90deg,var(--paper) 0 72%,color-mix(in srgb,var(--secondary) 18%,var(--paper)) 72%); }
    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(1200px,calc(100% - 38px));margin:auto;padding:76px 0}.mast{display:grid;grid-template-columns:2fr 1fr;gap:7vw;align-items:center;margin-bottom:44px}.mast h1{font-family:Baskerville,"Songti SC",serif;font-weight:800;font-size:clamp(48px,11vw,112px);line-height:.86;letter-spacing:-.06em;margin:0}.eyebrow{display:block;margin-bottom:22px;color:var(--accent);font:800 11px/1 ui-monospace,monospace;letter-spacing:.26em}.intro{max-width:46ch;margin-top:26px;font-size:17px;line-height:1.85}.scenario{align-self:end;padding-bottom:14px;border-bottom:5px solid var(--accent);font-weight:800}.demo{border-radius:0 60px 0 0;box-shadow:-16px 18px 0 color-mix(in srgb,var(--accent) 22%,transparent);position:relative;min-height:460px;overflow:hidden;padding:clamp(30px,6vw,72px);background:color-mix(in srgb,var(--paper) 92%,#fff)}@media(max-width:700px){.page{width:calc(100% - 22px);padding:30px 0}.mast{grid-template-columns:1fr}.demo{padding:20px}}
    .panel{padding:30px;border:0;border-radius:42px 12px;background:color-mix(in srgb,var(--secondary) 18%,var(--paper))}.row{display:flex;flex-wrap:wrap;gap:14px;align-items:center}.stack{display:flex;flex-direction:column;gap:20px}.action{min-height:48px;padding:12px 22px;border:0;border-radius:50% 50% 18px 18px;background:color-mix(in srgb,var(--secondary) 42%,transparent);font-weight:800}.action.primary,.action.is-active{color:var(--paper);background:var(--accent)}.muted{color:color-mix(in srgb,var(--ink) 64%,transparent);line-height:1.7}.status{min-height:25px;margin-top:16px;color:var(--accent)}.metric{font-size:clamp(32px,7vw,66px);font-weight:800}.meter{height:11px;border-radius:50%;background:color-mix(in srgb,var(--ink) 10%,transparent)}.meter>i{display:block;height:100%;border-radius:inherit;background:var(--accent)}.chip{padding:8px 12px;border-radius:50%;background:var(--paper)}
    .composition-studio{display:grid;gap:14px}.studio-ruler{display:flex;justify-content:space-between;padding:0 4px;color:color-mix(in srgb,var(--ink) 55%,transparent);font:700 11px/1 ui-monospace,monospace;letter-spacing:.14em}.studio-ruler::before{content:"01 / WORKING PROTOTYPE"}.studio-ruler::after{content:"360 · 768 · 1440"}.composition-studio .demo::after{content:"";position:absolute;right:18px;bottom:18px;width:24px;height:24px;border-right:2px solid var(--accent);border-bottom:2px solid var(--accent);pointer-events:none}
    .stepper-studio{display:grid;gap:18px;max-width:920px;margin:auto}.stepper-studio header{display:flex;justify-content:space-between;gap:18px;align-items:end}.stepper-studio h2{margin:.2em 0;font-size:clamp(38px,8vw,82px)}.stepper-board{display:grid;grid-template-columns:minmax(220px,.42fr) minmax(0,1fr);gap:16px}.stepper-stage,.stepper-breakdown{display:grid;gap:14px;padding:22px;border:1px solid var(--line);border-radius:22px;background:var(--paper)}.stepper-stage strong{font-size:clamp(54px,10vw,104px);line-height:.9}.stepper-direct{display:grid;gap:6px;font-weight:800}.stepper-direct input{width:100%;padding:10px;border:1px solid var(--line);border-radius:12px;background:var(--paper);font-size:22px;font-weight:900}.stepper-controls{display:grid;grid-template-columns:repeat(2,1fr);gap:10px}.stepper-controls button{min-height:56px;border:1px solid var(--ink);border-radius:16px;background:var(--ink);color:var(--paper);font-size:30px}.stepper-shortcuts{display:flex;flex-wrap:wrap;gap:8px}.stepper-shortcuts button{min-width:56px;padding:9px 12px;border:1px solid var(--line);border-radius:999px;background:transparent}.stepper-shortcuts button[aria-pressed="true"]{color:var(--paper);background:var(--accent)}#stepperSlots{display:grid;gap:12px;padding:0;margin:0;list-style:none}#stepperSlots li{display:grid;grid-template-columns:auto 52px 1fr;gap:12px;align-items:center}#stepperSlots strong{font-size:30px}#stepperSlots i{display:block;height:12px;overflow:hidden;border-radius:999px;background:var(--line)}#stepperSlots b{display:block;height:100%;width:0;background:var(--accent)}@media(max-width:700px){.stepper-studio header{align-items:stretch;flex-direction:column}.stepper-board{grid-template-columns:1fr}}.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="magazine" data-composition="studio">
  <main class="page">
    <header class="mast"><div><span class="eyebrow">magazine / Numeric Stepper / BEGINNER</span><h1>Loft lounge numeric stepper</h1><p class="intro">Complete the numeric stepper in the loft lounge scene: includes real content, interactive controls, clear status feedback, and responsive layout across sizes.</p></div><span class="scenario">Loft Lounge Table</span></header>
    <div class="composition-studio"><div class="studio-ruler" aria-hidden="true"></div><section class="demo" aria-label="Loft Lounge Numeric Stepper Interactive Area"><div class="workflow-dispatch"><aside class="dispatch-console"><span class="eyebrow">Loft lounge desk DISPATCH</span><h2>Loft Lounge Control Desk</h2><form id="workflowDispatchForm"><label>Task Type<select id="workflowDispatchKind"><option>Loft Lounge Manual Mode</option><option>Loft Lounge Smart Mode</option><option>Loft Lounge Linked Mode</option></select></label><label>Device Load<input id="workflowDispatchAmount" type="number" min="1" max="9999" value="33"><span>%</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">Application scenarios</button></form><label>Current task<select id="workflowDispatchActive" aria-label="Switch current task"><option value="1">Loft Lounge Manual Mode</option><option value="2">Loft Lounge Smart Mode</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:controls-selectors-numeric-stepper --><section class="stepper-studio"><header><div><span class="eyebrow">NUMBER STEPPER</span><h2>Loft Lounge Quota Desk</h2><p>Use buttons to assign quantities, then split the results into three processing sections.</p></div><output id="stepperCapacity">8 spots left</output></header><div class="stepper-board"><aside class="stepper-stage"><strong id="stepperValue">4</strong><p>Current Quantity</p><label class="stepper-direct"><span>Enter quantity directly</span><input id="stepperInput" type="number" min="1" max="12" step="1" value="4" inputmode="numeric"></label><div class="stepper-controls"><button id="stepperMinus" type="button" aria-label="Reduce by one slot">−</button><button id="stepperPlus" type="button" aria-label="Add one slot" data-core-bridge="controls-selectors-numeric-stepper">+</button></div><div class="stepper-shortcuts"><button type="button" data-stepper-value="2">2</button><button type="button" data-stepper-value="4">4</button><button type="button" data-stepper-value="8">8</button><button type="button" data-stepper-value="12">12</button></div></aside><section class="stepper-breakdown"><ol id="stepperSlots"><li><span>Prep Area</span><strong id="stepperSlot0">0</strong><i><b id="stepperFill0"></b></i></li><li><span>Distribution Area</span><strong id="stepperSlot1">0</strong><i><b id="stepperFill1"></b></i></li><li><span>Confirmation Area</span><strong id="stepperSlot2">0</strong><i><b id="stepperFill2"></b></i></li></ol><p id="stepperSummary">Preparation area 2 items, distribution area 1 items, confirmation area 1 items.</p></section></div></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:controls-selectors-numeric-stepper */
const stepperValue=document.querySelector('#stepperValue');const stepperInput=document.querySelector('#stepperInput');const stepperCapacity=document.querySelector('#stepperCapacity');const stepperSummary=document.querySelector('#stepperSummary');const stepperShortcuts=[...document.querySelectorAll('[data-stepper-value]')];function splitStepper(value){const head=Math.ceil(value/2);const tail=value-head;const middle=Math.ceil(tail/2);return [head,middle,Math.max(0,value-head-middle)];}function renderStepper(next){const value=Math.min(12,Math.max(1,Number(next)||1));const slots=splitStepper(value);stepperValue.textContent=String(value);stepperInput.value=String(value);stepperCapacity.textContent='Remaining '+(12-value)+' places';document.querySelector('#stepperMinus').disabled=value===1;document.querySelector('#stepperPlus').disabled=value===12;slots.forEach((count,index)=>{document.querySelector('#stepperSlot'+index).textContent=String(count);document.querySelector('#stepperFill'+index).style.width=Math.round(count/Math.max(1,value)*100)+'%';});stepperSummary.textContent='Prep Area '+slots[0]+' item, distribution area '+slots[1]+' units, confirm area '+slots[2]+' item.';stepperShortcuts.forEach(button=>button.setAttribute('aria-pressed',String(Number(button.dataset.stepperValue)===value)));announce('Current Quantity '+value);}document.querySelector('#stepperMinus').addEventListener('click',()=>renderStepper(Number(stepperInput.value)-1));document.querySelector('#stepperPlus').addEventListener('click',()=>renderStepper(Number(stepperInput.value)+1));stepperInput.addEventListener('input',()=>renderStepper(stepperInput.value));stepperShortcuts.forEach(button=>button.addEventListener('click',()=>renderStepper(button.dataset.stepperValue)));renderStepper(4);
/* 11DZ_CORE_SCRIPT_END */
const workflowBridgeSpec={"name":"controls-selectors-numeric-stepper","selector":"[data-core-bridge=\"controls-selectors-numeric-stepper\"]","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":"Loft Lounge Manual Mode","amount":12,"priority":"normal","touches":0}],["2",{"label":"Loft Lounge Smart Mode","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+' % · '+bridge.summary;announce('Loft Lounge Table current task:'+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+' % · '+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