Masque de progression du centre des membres
Créez un voile de progression dans un contexte de centre des membres : avec contenu réel, contrôles actionnables, retours d’état clairs et disposition adaptative aux différentes tailles d’écran.
Après activation de JavaScript, ce cas peut être modifié, exécuté et enregistré. Code source fixe ci-dessous :
<!doctype html>
<html lang="fr" dir="ltr">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Masque de progression du centre des membres</title>
<style>
:root { --ink:#18332f; --paper:#f4efe4; --accent:#d45f3e; --secondary:#8fc4ad; --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:"Kaiti SC",STKaiti,"Songti SC",serif; background:radial-gradient(circle at 12% 18%,color-mix(in srgb,var(--accent) 12%,transparent) 0 1px,transparent 2px),var(--paper);background-size:19px 19px; }
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(980px,calc(100% - 32px));margin:auto;padding:72px 0 92px}.mast{display:grid;grid-template-columns:1fr auto;transform:rotate(-.25deg);gap:32px;align-items:center;margin-bottom:46px}.mast h1{font-family:"Kaiti SC",STKaiti,serif;font-weight:700;font-size:clamp(40px,8vw,84px);letter-spacing:.02em;margin:0;line-height:1.12}.intro{max-width:650px;margin-top:18px;line-height:2}.scenario{padding:12px;border:2px solid var(--accent);color:var(--accent);transform:rotate(3deg)}.eyebrow{display:block;margin-bottom:9px;color:var(--accent);letter-spacing:.18em}.demo{border-radius:2px;transform:rotate(.12deg);box-shadow:0 30px 70px color-mix(in srgb,var(--ink) 18%,transparent);position:relative;min-height:430px;overflow:hidden;padding:clamp(28px,6vw,66px);background:color-mix(in srgb,var(--paper) 92%,#fff)}@media(max-width:700px){.page{width:calc(100% - 20px);padding:28px 0}.mast{grid-template-columns:1fr}.scenario{justify-self:start}.demo{padding:20px}}
.panel{padding:18px;border:3px solid var(--ink);background:var(--paper);box-shadow:8px 8px 0 var(--ink)}.stack{display:grid;gap:12px}.row{display:flex;flex-wrap:wrap;gap:8px}.action{min-height:42px;padding:8px 13px;border:3px solid var(--ink);background:var(--paper);font-weight:900}.action.primary,.action.is-active{color:var(--paper);background:var(--ink)}.status{min-height:24px;padding:8px;color:var(--paper);background:var(--ink);font-weight:900}.metric{font-size:clamp(34px,8vw,76px);font-weight:900;letter-spacing:-.08em}.muted{font-weight:600}.chip{padding:5px 8px;border:2px solid var(--ink);font-weight:900}.meter{height:14px;border:3px solid var(--ink)}.meter>i{display:block;height:100%;background:var(--ink)}
.composition-index{position:relative;display:grid;grid-template-columns:minmax(0,1fr) auto;gap:18px}.index-mark{display:grid;align-content:space-between;width:76px;padding:16px 10px;border:1px solid var(--line);color:var(--accent);background:color-mix(in srgb,var(--paper) 82%,transparent);text-align:center}.index-mark strong{font:900 34px/1 ui-monospace,monospace}.index-mark span{writing-mode:vertical-rl;font:800 10px/1.2 ui-monospace,monospace;letter-spacing:.18em}.composition-index .demo{grid-column:1;grid-row:1}.composition-index::before{content:"";position:absolute;left:-12px;top:38px;width:5px;height:45%;background:linear-gradient(var(--accent),var(--secondary))}@media(max-width:700px){.composition-index{grid-template-columns:1fr}.index-mark{grid-row:1;width:auto;grid-template-columns:auto 1fr}.index-mark span{writing-mode:horizontal-tb}.composition-index .demo{grid-row:2}}
.blocker-stage{display:grid;grid-template-columns:minmax(0,1fr) minmax(250px,.65fr);gap:18px;align-items:center;min-height:390px;padding:clamp(24px,6vw,64px);border:1px solid var(--line);border-radius:30px;background:var(--paper)}.blocker-stage h2{grid-column:1;margin:.2em 0;font-size:clamp(34px,7vw,74px)}.blocker-stage p,.blocker-stage>.action{grid-column:1}.blocker-stage>.action{justify-self:start}.blocker-stage ul{grid-column:2;grid-row:1/5;display:grid;gap:8px;margin:0;padding:0;list-style:none}.blocker-stage li{display:flex;justify-content:space-between;gap:12px;padding:15px;border:1px solid var(--line);border-radius:12px}.blocker-stage li span{opacity:.55}.progress-blocker-demo dialog{width:min(470px,calc(100% - 28px));padding:36px;border:0;border-radius:28px;color:var(--ink);background:var(--paper);box-shadow:0 30px 100px #0008;text-align:center}.progress-blocker-demo dialog::backdrop{background:#07110dc7;backdrop-filter:blur(7px)}.blocker-spinner{display:grid;width:92px;aspect-ratio:1;place-items:center;margin:0 auto 20px;border:2px solid var(--line);border-radius:50%}.blocker-spinner i{width:54px;aspect-ratio:1;border:7px solid var(--line);border-top-color:var(--accent);border-radius:50%;animation:blockerSpin .8s linear infinite}.progress-blocker-demo dialog h2{margin:.25em 0}.blocker-progress{height:12px;overflow:hidden;border-radius:999px;background:var(--line)}.blocker-progress i{display:block;width:0;height:100%;background:linear-gradient(90deg,var(--accent),var(--secondary));transition:width .18s}.progress-blocker-demo dialog output{display:block;margin:12px;font-size:28px;font-weight:900}.progress-blocker-demo dialog button{padding:10px 16px;border:1px solid var(--line);border-radius:10px;background:transparent}@keyframes blockerSpin{to{transform:rotate(1turn)}}@media(max-width:650px){.blocker-stage{grid-template-columns:1fr}.blocker-stage h2,.blocker-stage p,.blocker-stage>.action,.blocker-stage ul{grid-column:auto;grid-row:auto}}.workflow-compare{display:grid;grid-template-columns:minmax(230px,.55fr) minmax(0,1.45fr);gap:18px}.compare-stage{display:grid;gap:12px;min-width:0}.compare-stage>header{display:flex;justify-content:space-between;gap:16px;align-items:end}.compare-stage h2{margin:.2em 0}.compare-core{--compare-split:50%;min-width:0;padding:14px;clip-path:inset(0 calc(100% - var(--compare-split)) 0 0);outline:1px dashed var(--accent);outline-offset:-8px;transition:clip-path .25s,filter .25s}.compare-core[data-compare-channel="B"]{filter:hue-rotate(32deg) saturate(1.15)}.compare-controls{display:grid;align-content:start;gap:16px;padding:20px;border:1px solid var(--line);border-radius:24px 4px 24px 4px;background:var(--paper)}.compare-controls fieldset,.compare-controls>label{display:grid;gap:8px}.compare-controls input[type="range"]{width:100%}#workflowCompareShelf{display:grid;gap:6px;padding:0;margin:0;list-style:none}#workflowCompareShelf li{display:grid;grid-template-columns:auto 1fr auto;gap:8px;padding:9px;border-top:1px solid var(--line);font-size:12px}@media(max-width:900px){.workflow-compare{grid-template-columns:1fr}.compare-stage{order:-1}.compare-core{clip-path:none;border-left:8px solid var(--accent)}}
</style>
</head>
<body data-aesthetic="paper" data-composition="field-index">
<main class="page">
<header class="mast"><div><span class="eyebrow">paper / masque de progression / INTERMEDIATE</span><h1>Masque de progression du centre des membres</h1><p class="intro">Créez un voile de progression dans un contexte de centre des membres : avec contenu réel, contrôles actionnables, retours d’état clairs et disposition adaptative aux différentes tailles d’écran.</p></div><span class="scenario">Centre des membres</span></header>
<div class="composition-index"><section class="demo" aria-label="Zone interactive du masque de progression du centre d’adhésion"><div class="workflow-compare"><form id="workflowCompareControls" class="compare-controls"><fieldset><legend>Canal de comparaison</legend><label><input type="radio" name="workflowChannel" value="A" checked>A · Panneau ouvert du centre d’adhésion</label><label><input type="radio" name="workflowChannel" value="B">B · Traitement du centre d’adhésion en cours</label></fieldset><label>Charge de tâches en attente pondérée<input id="workflowCompareWeight" type="range" min="10" max="90" value="50"><output id="workflowCompareWeightValue">élément 50</output></label><label><input id="workflowCompareFreeze" type="checkbox">Geler la version actuelle</label><button id="workflowCompareCapture" class="action primary" type="button">Prélever un échantillon et terminer le traitement</button><ol id="workflowCompareShelf" aria-label="Enregistrement de version"></ol></form><section class="compare-stage"><header><span class="eyebrow">Centre des adhésions COMPARE</span><h2>Comparatif des deux versions du centre d’adhésion</h2><output id="workflowCompareLive">Version A en attente d’échantillonnage</output></header><section id="workflowCore" class="workflow-core compare-core" data-compare-channel="A" style="--compare-split:50%"><!-- 11DZ_CORE_START:overlays-feedback-progress-blocker --><section class="progress-blocker-demo"><div class="blocker-stage"><span class="eyebrow">PROGRESS BLOCKER</span><h2>Traiter les tâches du centre d’adhésion</h2><p>L’indicateur de progression modal s’affiche uniquement après un lancement explicite ; l’utilisateur peut l’annuler à tout moment.</p><button id="blockerStart" class="action primary" type="button" data-core-bridge="overlays-feedback-progress-blocker">Commencer le traitement</button><ul><li>Vue d’ensemble du centre d’adhésion<span>En attente</span></li><li>Plan du centre d’adhésion<span>En attente</span></li><li>Inspiration pour le centre membres<span>En attente</span></li></ul></div><dialog id="progressBlocker" aria-labelledby="blockerTitle"><div class="blocker-spinner" aria-hidden="true"><i></i></div><span class="eyebrow">PROCESSING</span><h2 id="blockerTitle">En cours de traitement localement</h2><p id="blockerMessage">Préparation des données…</p><div class="blocker-progress" role="progressbar" aria-label="Progression du traitement" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0"><i id="blockerMeter"></i></div><output id="blockerValue">0%</output><button id="blockerCancel" type="button">Annuler le traitement</button></dialog></section><!-- 11DZ_CORE_END --></section></section></div><p id="status" class="status" role="status" aria-live="polite"></p></section><aside class="index-mark" aria-hidden="true"><strong>05</strong><span>Centre des membres FIELD INDEX</span></aside></div>
</main>
<script>
'use strict';
const statusOutput = document.querySelector('#status');
const announce = message => { statusOutput.textContent = message; };
/* 11DZ_CORE_SCRIPT_START:overlays-feedback-progress-blocker */
const progressBlocker=document.querySelector('#progressBlocker');const blockerProgress=progressBlocker.querySelector('[role="progressbar"]');const blockerMeter=document.querySelector('#blockerMeter');const blockerValue=document.querySelector('#blockerValue');const blockerMessage=document.querySelector('#blockerMessage');let blockerTimer=0;let blockerCloseTimer=0;let blockerAmount=0;function cancelBlocker(message){clearInterval(blockerTimer);clearTimeout(blockerCloseTimer);blockerTimer=0;blockerCloseTimer=0;if(progressBlocker.open)progressBlocker.close();announce(message);}document.querySelector('#blockerStart').addEventListener('click',()=>{blockerAmount=0;blockerMeter.style.width='0%';blockerValue.textContent='0%';blockerProgress.setAttribute('aria-valuenow','0');blockerMessage.textContent='Préparation des données…';progressBlocker.showModal();blockerTimer=setInterval(()=>{blockerAmount=Math.min(100,blockerAmount+10);blockerMeter.style.width=blockerAmount+'%';blockerValue.textContent=blockerAmount+'%';blockerProgress.setAttribute('aria-valuenow',String(blockerAmount));blockerMessage.textContent=blockerAmount<40?'Préparation des données…':blockerAmount<80?'Paramètres de l’application…':'Vérification terminée…';if(blockerAmount===100){clearInterval(blockerTimer);blockerTimer=0;blockerCloseTimer=setTimeout(()=>cancelBlocker('Le traitement local est terminé'),350);}},160);});document.querySelector('#blockerCancel').addEventListener('click',()=>cancelBlocker('Traitement annulé'));progressBlocker.addEventListener('cancel',event=>{event.preventDefault();cancelBlocker('Traitement annulé');});
/* 11DZ_CORE_SCRIPT_END */
const workflowBridgeSpec={"name":"overlays-feedback-progress-blocker","selector":"[data-core-bridge=\"overlays-feedback-progress-blocker\"]","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+' · Version de base '+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 workflowCompareCore=document.querySelector('#workflowCore');const workflowCompareWeight=document.querySelector('#workflowCompareWeight');const workflowCompareState={channel:'A',weight:50,frozen:false,snapshots:[]};function workflowCompareFingerprint(){const controls=[...workflowCompareCore.querySelectorAll('input,select,textarea')];const outputs=[...workflowCompareCore.querySelectorAll('output,[role="status"],strong')].map(node=>node.textContent.trim()).filter(Boolean);return {controlValues:controls.map(control=>control.type==='checkbox'||control.type==='radio'?control.checked:control.value),summary:outputs.slice(0,4).join(' / '),nodes:workflowCompareCore.querySelectorAll('*').length};}function workflowCompareDrive(){workflowCompareCore.dataset.compareChannel=workflowCompareState.channel;workflowCompareCore.style.setProperty('--compare-split',workflowCompareState.weight+'%');document.querySelector('#workflowCompareWeightValue').textContent=workflowCompareState.weight+' élément';document.querySelector('#workflowCompareLive').textContent=workflowCompareState.channel+' Version · '+workflowCompareState.weight+' élément'+(workflowCompareState.frozen?' · figé':'');announce('Le centre d’adhésion est en cours d’affichage '+workflowCompareState.channel+' Version');}function workflowCompareCapture(source){const bridge=workflowBridgeActivate();const snapshot={...workflowCompareFingerprint(),channel:workflowCompareState.channel,weight:workflowCompareState.weight,source,bridge:bridge.summary};workflowCompareState.snapshots.push(snapshot);const item=document.createElement('li');item.innerHTML='<b>'+snapshot.channel+'</b><span>'+(snapshot.summary||snapshot.bridge)+'</span><small>'+snapshot.weight+' élément · '+snapshot.bridge+'</small>';document.querySelector('#workflowCompareShelf').prepend(item);announce('échantillonné '+snapshot.channel+' Version et traitement terminés · '+bridge.summary);}document.querySelectorAll('[name="workflowChannel"]').forEach(input=>input.addEventListener('change',()=>{workflowCompareState.channel=input.value;workflowCompareDrive();}));workflowCompareWeight.addEventListener('input',()=>{workflowCompareState.weight=Number(workflowCompareWeight.value);workflowCompareDrive();});document.querySelector('#workflowCompareFreeze').addEventListener('change',event=>{workflowCompareState.frozen=event.currentTarget.checked;workflowCompareDrive();});document.querySelector('#workflowCompareCapture').addEventListener('click',()=>workflowCompareCapture('Échantillonnage du bouton'));workflowCompareCore.addEventListener('dblclick',()=>workflowCompareCapture('Double-clic sur la vue principale'));workflowCompareDrive();
workflowBridgeReset();
</script>
</body>
</html>