Architecture de contenu maître-esclave pour journal
Réalisez une mise en page de contenu maître-détail dans un contexte de journal d’architecture : elle doit inclure du contenu réel, des contrôles actionnables, un retour d’état clair et une disposition adaptée 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>Architecture de contenu maître-esclave pour journal</title>
<style>
:root { --ink:#30231f; --paper:#f9efe5; --accent:#8b6fb0; --secondary:#d7a971; --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-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}}
.master-detail-demo{display:grid;grid-template-columns:minmax(220px,.7fr) minmax(300px,1.3fr);min-height:390px;border:1px solid var(--line);border-radius:20px;overflow:hidden;background:var(--paper)}.master-detail-demo nav{display:grid;align-content:start;border-right:1px solid var(--line)}.master-detail-demo nav button{display:grid;gap:5px;padding:15px;border:0;border-bottom:1px solid var(--line);text-align:left;background:transparent}.master-detail-demo nav button[aria-current="true"]{color:var(--paper);background:var(--ink)}.master-detail-demo nav small{opacity:.65}.master-detail-demo article{display:grid;align-content:center;padding:clamp(28px,6vw,66px)}.master-detail-demo article h2{font-size:clamp(34px,7vw,72px)}.master-detail-demo dl div{display:flex;gap:18px;justify-content:space-between}.master-detail-demo dd{font-weight:900}@media(max-width:620px){.master-detail-demo{grid-template-columns:1fr}.master-detail-demo nav{grid-auto-flow:column;overflow:auto;border-right:0;border-bottom:1px solid var(--line)}.master-detail-demo nav button{min-width:180px}}.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="paper" data-composition="split-note">
<main class="page">
<header class="mast"><div><span class="eyebrow">paper / mise en page à contenu maître-esclave / INTERMEDIATE</span><h1>Architecture de contenu maître-esclave pour journal</h1><p class="intro">Réalisez une mise en page de contenu maître-détail dans un contexte de journal d’architecture : elle doit inclure du contenu réel, des contrôles actionnables, un retour d’état clair et une disposition adaptée aux différentes tailles d’écran.</p></div><span class="scenario">Journal d’architecture</span></header>
<div class="composition-split"><aside class="split-note"><b>CASE 02</b><span>Maîtriser la structure sémantique, l’agencement responsive, l’utilisation du clavier et la synchronisation des états des mises en page maître-esclave.</span></aside><section class="demo" aria-label="Zone interactive de la mise en page contenu principal–détails du journal d’architecture"><div class="workflow-dispatch"><aside class="dispatch-console"><span class="eyebrow">Journal d’architecture DISPATCH</span><h2>Poste de travail pour la rédaction architecturale</h2><form id="workflowDispatchForm"><label>Type de tâche<select id="workflowDispatchKind"><option>Étude de façade</option><option>Étude des matériaux</option><option>Étude spatiale</option></select></label><label>Nombre de mises en page<input id="workflowDispatchAmount" type="number" min="1" max="9999" value="45"><span>page</span></label><fieldset><legend>Priorité de traitement</legend><label><input type="radio" name="workflowPriority" value="normal" checked>Standard</label><label><input type="radio" name="workflowPriority" value="urgent">Urgent</label></fieldset><button class="action primary" type="submit">Entrer dans la composition</button></form><label>Tâche en cours<select id="workflowDispatchActive" aria-label="Basculer la tâche en cours"><option value="1">Étude de façade</option><option value="2">Étude des matériaux</option></select></label><output id="workflowDispatchSummary">En attente de planification</output></aside><section id="workflowCore" class="workflow-core dispatch-workbench" data-dispatch-priority="normal"><!-- 11DZ_CORE_START:layouts-responsive-master-detail --><div class="master-detail-demo"><nav aria-label="Liste des enregistrements"><button type="button" data-master-index="0" aria-current="true" data-core-bridge="layouts-responsive-master-detail"><b>Rappel du journal d’architecture</b><small>Journal 01</small></button><button type="button" data-master-index="1"><b>Collecte d’architecture du journal</b><small>Consigner 02</small></button><button type="button" data-master-index="2"><b>Aperçu de l’architecture</b><small>Journal 03</small></button><button type="button" data-master-index="3"><b>Projet Journal d’architecture</b><small>Journal de 04</small></button><button type="button" data-master-index="4"><b>Inspiration d’une chronique d’architecture</b><small>Enregistrement 05</small></button><button type="button" data-master-index="5"><b>Chronique architecturale</b><small>Enregistrer 06</small></button></nav><article id="detailPanel" tabindex="-1"><span class="eyebrow">MASTER DETAIL</span><h2>Rappel du journal d’architecture</h2><p>Sélectionnez un enregistrement dans la liste principale ; le détail à droite se met à jour à son emplacement d’origine ; sur les petits écrans, les éléments s’empilent verticalement.</p><dl><div><dt>Scénario</dt><dd>Journal d’architecture</dd></div><div><dt>État</dt><dd id="detailStatus">En cours</dd></div></dl></article></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:layouts-responsive-master-detail */
const masterRecords=["Rappel du journal d’architecture","Collecte d’architecture du journal","Aperçu de l’architecture","Projet Journal d’architecture","Inspiration d’une chronique d’architecture","Chronique architecturale"];const masterButtons=[...document.querySelectorAll('[data-master-index]')];masterButtons.forEach((button,index)=>button.addEventListener('click',()=>{masterButtons.forEach(item=>item.removeAttribute('aria-current'));button.setAttribute('aria-current','true');document.querySelector('#detailPanel h2').textContent=masterRecords[index];document.querySelector('#detailStatus').textContent=['En cours','À réviser','Terminé'][index%3];document.querySelector('#detailPanel').focus();announce('Ouvert '+masterRecords[index]+' Détails');}));
/* 11DZ_CORE_SCRIPT_END */
const workflowBridgeSpec={"name":"layouts-responsive-master-detail","selector":"[data-core-bridge=\"layouts-responsive-master-detail\"]","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 workflowDispatchCore=document.querySelector('#workflowCore');const workflowDispatchForm=document.querySelector('#workflowDispatchForm');const workflowDispatchSelect=document.querySelector('#workflowDispatchActive');const workflowDispatchJobs=new Map([["1",{"label":"Étude de façade","amount":12,"priority":"normal","touches":0}],["2",{"label":"Étude des matériaux","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+' Page · '+bridge.summary;announce('Tâches en cours pour le projet architectural :'+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+' Page · '+workflowBridgeSummary();});workflowDispatchRender('1',false);
workflowBridgeReset();
</script>
</body>
</html>