Composants de base et sélecteurs

Régulateur de plage du plan de voyage

Créer un régulateur de plage pour un scénario de planification de voyage : contenu réel, contrôles actionnables, retours d’état clairs et mise en page sur plusieurs tailles d’écran.

Composants de base et sélecteursRégulateur de plageHTMLCSSJavaScript
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>Régulateur de plage du plan de voyage</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:"Hiragino Maru Gothic ProN","PingFang SC",sans-serif; background:radial-gradient(circle at 15% 10%,color-mix(in srgb,var(--secondary) 35%,transparent) 0 9%,transparent 10%),radial-gradient(circle at 90% 75%,color-mix(in srgb,var(--accent) 18%,transparent) 0 12%,transparent 13%),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(1140px,calc(100% - 28px));margin:auto;padding:54px 0}.mast{display:flex;justify-content:space-between;align-items:center;gap:24px;margin:0 12px 28px}.mast h1{font-family:"Hiragino Maru Gothic ProN","PingFang SC",sans-serif;font-weight:900;font-size:clamp(38px,8vw,82px);letter-spacing:-.035em;margin:0;line-height:.98}.eyebrow{display:inline-flex;padding:7px 12px;border-radius:999px;color:var(--paper);background:var(--accent);font-weight:900}.intro{max-width:620px;line-height:1.65}.scenario{padding:12px 18px;border-radius:999px;background:var(--secondary);box-shadow:0 7px 0 color-mix(in srgb,var(--ink) 18%,transparent);font-weight:900}.demo{border-radius:46px 18px 46px 18px;box-shadow:0 18px 0 color-mix(in srgb,var(--secondary) 45%,transparent);position:relative;min-height:390px;overflow:hidden;padding:clamp(22px,5vw,54px);background:color-mix(in srgb,var(--paper) 90%,#fff)}@media(max-width:700px){.mast{display:grid}.page{width:calc(100% - 16px);padding:18px 0}.demo{padding:17px}}
    .panel{padding:18px;border:2px solid var(--line);border-radius:26px;box-shadow:0 12px 0 color-mix(in srgb,var(--secondary) 35%,transparent)}.row{display:flex;gap:12px;justify-content:center;flex-wrap:wrap}.stack{display:grid;gap:12px}.action{padding:12px 20px;border:2px solid var(--ink);border-radius:14px;background:var(--paper);box-shadow:0 5px 0 var(--ink);font-weight:800}.action:active{transform:translateY(4px);box-shadow:0 1px 0 var(--ink)}.action.primary,.action.is-active{color:var(--paper);background:var(--accent)}.status{text-align:center;min-height:26px;margin-top:18px}.metric{text-align:center;font-size:clamp(34px,8vw,70px);font-weight:900}.muted{text-align:center;opacity:.7}.meter{height:14px;padding:2px;border:2px solid var(--ink);border-radius:999px}.meter>i{display:block;height:100%;border-radius:inherit;background:var(--secondary)}.chip{padding:7px 11px;border-radius:12px;background:color-mix(in srgb,var(--accent) 12%,transparent)}
    .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}}
    .range-mixer-demo{display:grid;grid-template-columns:minmax(0,1fr) minmax(240px,.75fr);gap:20px}.mixer-console{display:grid;gap:19px;padding:clamp(22px,4vw,42px);border:1px solid var(--line);background:var(--paper)}.mixer-console h2{margin:0;font-size:clamp(28px,5vw,52px)}.mixer-console label{display:grid;gap:9px}.mixer-console label>span{display:flex;justify-content:space-between;font-weight:800}.mixer-console input{width:100%}.mixer-preview{--level:55;display:grid;place-content:center;justify-items:center;gap:14px;min-height:360px;padding:24px;border-radius:32px;background:linear-gradient(145deg,color-mix(in srgb,var(--secondary) calc(var(--level)*1%),var(--paper)),var(--ink));color:var(--paper);text-align:center}.mixer-disc{width:clamp(120px,20vw,210px);aspect-ratio:1;border:18px solid color-mix(in srgb,var(--paper) 28%,transparent);border-radius:50%;background:conic-gradient(var(--accent) calc(var(--level)*1%),transparent 0);box-shadow:inset 0 0 0 24px var(--ink)}.mixer-preview strong{font-size:clamp(28px,5vw,48px)}@media(max-width:700px){.range-mixer-demo{grid-template-columns:1fr}.mixer-preview{min-height:270px}}.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="playful" data-composition="split-note">
  <main class="page">
    <header class="mast"><div><span class="eyebrow">playful / régulateur de plage / INTERMEDIATE</span><h1>Régulateur de plage du plan de voyage</h1><p class="intro">Créer un régulateur de plage pour un scénario de planification de voyage : contenu réel, contrôles actionnables, retours d’état clairs et mise en page sur plusieurs tailles d’écran.</p></div><span class="scenario">Plan de voyage</span></header>
    <div class="composition-split"><aside class="split-note"><b>CASE 02</b><span>Maîtriser la structure sémantique, la composition réactive, la navigation au clavier et la synchronisation d’état du sélecteur de plage.</span></aside><section class="demo" aria-label="Zone interactive du régulateur de plage du plan de voyage"><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 · itinéraire rapide</label><label><input type="radio" name="workflowChannel" value="B">B · Itinéraire équilibré</label></fieldset><label>Poids du budget du voyage<input id="workflowCompareWeight" type="range" min="10" max="90" value="50"><output id="workflowCompareWeightValue">50 yuan</output></label><label><input id="workflowCompareFreeze" type="checkbox">Geler la version actuelle</label><button id="workflowCompareCapture" class="action primary" type="button">Échantillonner et enregistrer l’itinéraire</button><ol id="workflowCompareShelf" aria-label="Enregistrement de version"></ol></form><section class="compare-stage"><header><span class="eyebrow">Plan de voyage COMPARE</span><h2>Comparaison des deux versions de l’itinéraire de voyage</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:controls-selectors-range-mixer --><section class="range-mixer-demo"><div class="mixer-console"><span class="eyebrow">RANGE MIXER</span><h2>Table de mixage du plan de voyage</h2><label><span>Rythme<output id="mixerValue0">42%</output></span><input type="range" min="0" max="100" value="42" data-mixer-range="0" aria-label="Rythme" data-core-bridge="controls-selectors-range-mixer"></label><label><span>Clair-obscur<output id="mixerValue1">68%</output></span><input type="range" min="0" max="100" value="68" data-mixer-range="1" aria-label="Clair-obscur"></label><label><span>Niveaux<output id="mixerValue2">54%</output></span><input type="range" min="0" max="100" value="54" data-mixer-range="2" aria-label="Niveaux"></label><button id="mixerReset" class="action" type="button">Rétablir l’équilibre</button></div><div id="mixerPreview" class="mixer-preview" aria-live="polite"><div class="mixer-disc"></div><strong id="mixerScore">Ajustement intégré 55%</strong><p>Plan de voyage</p></div></section><!-- 11DZ_CORE_END --></section></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-range-mixer */
const mixerRanges=[...document.querySelectorAll('[data-mixer-range]')];const mixerDefaults=[42,68,54];function renderMixer(){let total=0;mixerRanges.forEach((input,index)=>{total+=Number(input.value);document.querySelector('#mixerValue'+index).textContent=input.value+'%';});const score=Math.round(total/mixerRanges.length);document.querySelector('#mixerPreview').style.setProperty('--level',score);document.querySelector('#mixerScore').textContent='Synthèse '+score+'%';announce('Résultat du mixage '+score+'%');}mixerRanges.forEach(input=>input.addEventListener('input',renderMixer));document.querySelector('#mixerReset').addEventListener('click',()=>{mixerRanges.forEach((input,index)=>{input.value=mixerDefaults[index];});renderMixer();});renderMixer();
/* 11DZ_CORE_SCRIPT_END */
const workflowBridgeSpec={"name":"controls-selectors-range-mixer","selector":"[data-core-bridge=\"controls-selectors-range-mixer\"]","mode":"range","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+' · 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("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();const step=Number(workflowBridgeControl.step)||1;const min=workflowBridgeControl.min===''?-Infinity:Number(workflowBridgeControl.min);const max=workflowBridgeControl.max===''?Infinity:Number(workflowBridgeControl.max);let next=Math.min(max,Math.max(min,(Number(workflowBridgeControl.value)||0)+step));if(next===Number(workflowBridgeControl.value))next=Math.max(min,Number(workflowBridgeControl.value)-step);workflowBridgeControl.value=String(next);workflowBridgeControl.dispatchEvent(new Event('input',{bubbles:true}));workflowBridgeControl.dispatchEvent(new Event('change',{bubbles:true}));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+' yuan';document.querySelector('#workflowCompareLive').textContent=workflowCompareState.channel+' Version · '+workflowCompareState.weight+' yuan'+(workflowCompareState.frozen?' · figé':'');announce('la route de voyage est en cours de consultation '+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+' € · '+snapshot.bridge+'</small>';document.querySelector('#workflowCompareShelf').prepend(item);announce('échantillonné '+snapshot.channel+' Enregistrer et conserver l’itinéraire · '+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>
Commentaires sur la pageVous avez découvert un problème ou avez une suggestion d’amélioration ?
Les fonctions de retour nécessitent l’utilisation de la version en ligne

Veuillez activer JavaScript dans la version en ligne avant de soumettre ; les fonctionnalités locales de l’outil ou du cas ne sont pas affectées.

Aller vers la version en ligne pour envoyer des commentaires