Navegação por breadcrumb da sala de serviços ambulatoriais
Conclua a navegação por breadcrumbs em um cenário de posto de atendimento ambulatorial: inclui conteúdo real, controles acionáveis, feedback de estado claro e layout adaptável a vários tamanhos.
É possível editar, executar e salvar este exemplo após ativar JavaScript. O código-fonte fixo é o seguinte:
<!doctype html>
<html lang="pt-BR" dir="ltr">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Navegação por breadcrumb da sala de serviços ambulatoriais</title>
<style>
:root { --ink:#252525; --paper:#f7f2e8; --accent:#247ba0; --secondary:#f4b942; --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}}
.stack{display:flex;flex-direction:column;gap:18px}.panel{padding:28px;border-left:7px solid var(--accent);background:color-mix(in srgb,var(--secondary) 12%,var(--paper))}.action{min-height:46px;padding:11px 18px;border:0;border-bottom:3px solid var(--ink);background:transparent;font-weight:900}.action.primary,.action.is-active{color:var(--paper);background:var(--ink)}.row{display:grid;grid-template-columns:repeat(auto-fit,minmax(120px,1fr));gap:8px}.metric{font:900 clamp(32px,7vw,64px)/1 ui-monospace,monospace}.status{min-height:22px;padding-top:12px;border-top:1px dashed var(--line)}.muted{color:color-mix(in srgb,var(--ink) 62%,transparent)}.chip{display:inline-block;padding:5px 8px;background:var(--secondary)}.meter{height:12px;border:1px 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}}
.breadcrumb-studio{display:grid;gap:20px;max-width:920px;margin:auto}.breadcrumb-studio header{display:flex;justify-content:space-between;gap:18px;align-items:end}.breadcrumb-studio h2{margin:.35em 0}.crumb-trail{display:flex;flex-wrap:wrap;gap:9px;align-items:center;padding:18px;margin:0;border:1px solid var(--line);border-radius:18px;list-style:none;background:var(--paper)}.crumb-trail li{display:flex;gap:9px;align-items:center}.crumb-trail li:not(:last-child)::after{content:"/";color:var(--accent)}.crumb-trail a{color:inherit;text-underline-offset:4px}.crumb-trail [aria-current="page"]{font-weight:900}.crumb-builder{display:grid;grid-template-columns:minmax(200px,.8fr) auto;gap:14px;align-items:end}.crumb-builder label{display:grid;gap:8px;font-weight:800}.crumb-builder select{width:100%;padding:11px;border:1px solid var(--line);border-radius:10px;background:var(--paper)}.crumb-preview{display:grid;gap:8px;padding:18px;border-left:5px solid var(--accent);background:color-mix(in srgb,var(--secondary) 12%,transparent)}.breadcrumb-studio code{padding:3px 6px;background:color-mix(in srgb,var(--secondary) 20%,transparent)}@media(max-width:680px){.breadcrumb-studio header,.crumb-builder{align-items:stretch;flex-direction:column;display:flex}}.workflow-guide{display:grid;grid-template-columns:190px minmax(0,1fr);grid-template-areas:"rail core" "rail evidence";gap:14px 18px}.guide-rail{grid-area:rail;display:grid;align-content:start;gap:15px;padding:18px;border-right:1px solid var(--line)}.guide-rail ol{display:grid;gap:8px;padding:0;margin:0;list-style:none}.guide-rail li{display:grid;grid-template-columns:30px 1fr;gap:8px;align-items:center;padding:9px;opacity:.5}.guide-rail li[aria-current="step"]{opacity:1;color:var(--paper);background:var(--ink)}.guide-rail li.is-complete{opacity:1;color:var(--accent)}.guide-actions{display:grid;grid-template-columns:1fr 1fr;gap:7px}.guide-actions .action{padding-inline:8px}#workflowGuideProgress{height:6px;background:var(--line)}#workflowGuideProgress i{display:block;width:0;height:100%;background:var(--accent)}.guide-core{grid-area:core;min-width:0;padding:16px;border:1px solid var(--line)}.guide-core>p{margin:0 0 14px;padding:10px;border-left:4px solid var(--accent);background:color-mix(in srgb,var(--secondary) 12%,transparent)}.guide-core[data-guide-step="1"]{border-radius:28px}.guide-core[data-guide-step="2"]{box-shadow:inset 0 0 0 4px color-mix(in srgb,var(--accent) 35%,transparent)}.guide-evidence{grid-area:evidence;display:grid;grid-template-columns:1fr 1fr auto;gap:12px;align-items:start}.guide-evidence details,.guide-evidence form{padding:12px;border:1px solid var(--line)}.guide-evidence label{display:grid;gap:7px}.guide-evidence textarea{width:100%;padding:9px;border:1px solid var(--line);background:var(--paper)}@media(max-width:900px){.workflow-guide{grid-template-columns:1fr;grid-template-areas:"core" "rail" "evidence"}.guide-rail{border-right:0;border-bottom:1px solid var(--line)}.guide-rail ol{grid-template-columns:repeat(3,1fr)}.guide-evidence{grid-template-columns:1fr}}
</style>
</head>
<body data-aesthetic="playful" data-composition="split-note">
<main class="page">
<header class="mast"><div><span class="eyebrow">playful / navegação em breadcrumb / INTERMEDIATE</span><h1>Navegação por breadcrumb da sala de serviços ambulatoriais</h1><p class="intro">Conclua a navegação por breadcrumbs em um cenário de posto de atendimento ambulatorial: inclui conteúdo real, controles acionáveis, feedback de estado claro e layout adaptável a vários tamanhos.</p></div><span class="scenario">Sala de atendimento ambulatorial</span></header>
<div class="composition-split"><aside class="split-note"><b>CASE 02</b><span>Domine a estrutura semântica, o arranjo responsivo, a operação por teclado e a sincronização de estado da navegação por breadcrumb.</span></aside><section class="demo" aria-label="Área interativa de navegação por breadcrumbs do saguão de serviços ambulatoriais"><div class="workflow-guide"><nav class="guide-rail" aria-label="Guia do ambulatório"><span class="eyebrow">Sala de serviços ambulatoriais GUIDE</span><ol><li data-workflow-guide-step="0" aria-current="step"><b>1</b><span>Navegação da entrada para o hall de serviços ambulatoriais</span></li><li data-workflow-guide-step="1"><b>2</b><span>Navegação por caminho do salão de serviços ambulatoriais</span></li><li data-workflow-guide-step="2"><b>3</b><span>Navegação concluída do hall de atendimento ambulatorial</span></li></ol><div class="guide-actions"><button id="workflowGuideBack" class="action" type="button" disabled>Etapa anterior</button><button id="workflowGuideNext" class="action primary" type="button">Concluir esta etapa</button></div><div id="workflowGuideProgress" role="progressbar" aria-label="Concluído da sala de atendimento ambulatorial" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0"><i></i></div></nav><section id="workflowCore" class="workflow-core guide-core" data-guide-step="0" aria-describedby="workflowGuideInstruction"><p id="workflowGuideInstruction">Realize as operações relacionadas à navegação de entrada do "hall de serviços ambulatoriais" no caso principal.</p><!-- 11DZ_CORE_START:navigation-menus-breadcrumb-builder --><div class="breadcrumb-studio panel"><header><div><span class="eyebrow">BREADCRUMB BUILDER</span><h2>Oficina de caminhos do salão de serviços ambulatoriais</h2><p class="muted">Ao adicionar um novo nível, atualize também o caminho, a localização atual e o resumo do nível.</p></div><output id="crumbDepthStatus">3 caminho de nível</output></header><nav aria-label="breadcrumb"><ol id="crumbTrail" class="crumb-trail"></ol></nav><div class="crumb-builder"><label>Nome do próximo nível <select id="crumbChoice"><option>Progresso do hall de atendimento da clínica</option><option>Lembrete do hall de serviços ambulatoriais</option><option>Favoritos da sala de atendimento ambulatorial</option><option>Visão geral da recepção de serviços da clínica</option><option>Plano da ala de serviços da clínica</option><option>Inspiração da central de serviços ambulatoriais</option></select></label><div class="row"><button id="addCrumb" class="action primary" type="button" data-core-bridge="navigation-menus-breadcrumb-builder">Ir um nível mais fundo</button><button id="removeCrumb" class="action" type="button">Voltar ao nível anterior</button></div></div><aside id="crumbPreview" class="crumb-preview"><strong>Você está aqui</strong><p id="crumbPreviewText">Aguardando seleção do caminho</p></aside></div><!-- 11DZ_CORE_END --></section><aside class="guide-evidence"><details id="workflowGuideDetails"><summary>Ver requisitos de aceitação</summary><ul><li>A navegação de entrada do hall de serviços ambulatoriais precisa de uma mudança de estado visível de uma só vez</li><li>A navegação para o serviço ambulatorial requer uma mudança de estado visível</li><li>A conclusão da navegação no saguão de serviços ambulatoriais requer uma mudança de estado visível</li></ul></details><form id="workflowGuideEvidenceForm"><label>Evidência desta etapa<textarea id="workflowGuideEvidence" rows="3" placeholder="Registrar o estado observado"></textarea></label><input class="action" type="submit" value="Salvar evidência"></form><output id="workflowGuideSummary">0 / 3 passos concluídos</output></aside></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:navigation-menus-breadcrumb-builder */
const crumbChoices=["Progresso do hall de atendimento da clínica","Lembrete do hall de serviços ambulatoriais","Favoritos da sala de atendimento ambulatorial","Visão geral da recepção de serviços da clínica","Plano da ala de serviços da clínica","Inspiração da central de serviços ambulatoriais"];const crumbTrail=document.querySelector('#crumbTrail');const crumbChoice=document.querySelector('#crumbChoice');const crumbState=crumbChoices.slice(0,3);function renderCrumbs(){crumbTrail.replaceChildren();crumbState.forEach((label,index)=>{const item=document.createElement('li');if(index===crumbState.length-1){const current=document.createElement('span');current.textContent=label;current.setAttribute('aria-current','page');item.append(current);}else{const link=document.createElement('a');link.href='#crumb-'+index;link.textContent=label;link.addEventListener('click',event=>{event.preventDefault();crumbState.splice(index+1);renderCrumbs();});item.append(link);}crumbTrail.append(item);});document.querySelector('#crumbDepthStatus').textContent=crumbState.length+' caminho em níveis';document.querySelector('#crumbPreviewText').textContent=crumbState.join(' / ');announce('Caminho atual total '+crumbState.length+' nível');}document.querySelector('#addCrumb').addEventListener('click',()=>{const next=crumbChoice.value;if(crumbState.at(-1)===next)return announce('Atualmente em '+next);crumbState.push(next);renderCrumbs();});document.querySelector('#removeCrumb').addEventListener('click',()=>{if(crumbState.length===1)return;crumbState.pop();renderCrumbs();});renderCrumbs();
/* 11DZ_CORE_SCRIPT_END */
const workflowBridgeSpec={"name":"navigation-menus-breadcrumb-builder","selector":"[data-core-bridge=\"navigation-menus-breadcrumb-builder\"]","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+' · versão principal '+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 workflowGuideCore=document.querySelector('#workflowCore');const workflowGuideStages=["Navegação da entrada para o hall de serviços ambulatoriais","Navegação por caminho do salão de serviços ambulatoriais","Navegação concluída do hall de atendimento ambulatorial"];const workflowGuideState={step:0,completed:new Set(),evidence:new Map(),consumedVersion:0};function workflowGuideDrive(){const step=workflowGuideState.step;workflowGuideCore.dataset.guideStep=String(step);document.querySelector('#workflowGuideInstruction').textContent='Por favor, conclua no caso principal “'+workflowGuideStages[step]+'Ações relacionadas a ”.';document.querySelectorAll('[data-workflow-guide-step]').forEach((item,index)=>{item.classList.toggle('is-complete',workflowGuideState.completed.has(index));if(index===step)item.setAttribute('aria-current','step');else item.removeAttribute('aria-current');});document.querySelector('#workflowGuideBack').disabled=step===0;document.querySelector('#workflowGuideNext').textContent=step===workflowGuideStages.length-1?'Entrar no caminho':'Concluir esta etapa';const percent=Math.round(workflowGuideState.completed.size/workflowGuideStages.length*100);const progress=document.querySelector('#workflowGuideProgress');progress.setAttribute('aria-valuenow',String(percent));progress.querySelector('i').style.width=percent+'%';document.querySelector('#workflowGuideSummary').textContent=workflowGuideState.completed.size+' / '+workflowGuideStages.length+' Etapa concluída · '+workflowBridgeSummary();announce('Etapa atual do hall de serviços ambulatoriais:'+workflowGuideStages[step]);}function workflowGuideAdvance(direction){if(direction>0){const bridge=workflowBridgeActivate();const version=Number(workflowGuideCore.dataset.workflowVersion||0);if(version<=workflowGuideState.consumedVersion){announce('Complete primeiro a mudança visível de estado do caso principal');return;}workflowGuideState.consumedVersion=version;workflowGuideState.completed.add(workflowGuideState.step);announce('Mudanças do caso principal registradas · '+bridge.summary);}workflowGuideState.step=Math.max(0,Math.min(workflowGuideStages.length-1,workflowGuideState.step+direction));workflowGuideDrive();}document.querySelector('#workflowGuideBack').addEventListener('click',()=>workflowGuideAdvance(-1));document.querySelector('#workflowGuideNext').addEventListener('click',()=>workflowGuideAdvance(1));document.querySelector('#workflowGuideEvidenceForm').addEventListener('submit',event=>{event.preventDefault();const version=Number(workflowGuideCore.dataset.workflowVersion||0);if(version<=workflowGuideState.consumedVersion){announce('Prova não salva: o caso principal ainda não tem novas alterações');return;}const text=document.querySelector('#workflowGuideEvidence').value.trim();workflowGuideState.evidence.set(workflowGuideState.step,text||'Estado de visibilidade verificado como concluído');workflowGuideState.completed.add(workflowGuideState.step);workflowGuideState.consumedVersion=version;workflowGuideDrive();announce('Evidência desta etapa salva · '+workflowBridgeSummary());});document.querySelector('#workflowGuideDetails').addEventListener('toggle',event=>announce(event.currentTarget.open?'Requisitos de aceitação expandidos':'Requisitos de aceitação recolhidos'));workflowGuideDrive();
workflowBridgeReset();
</script>
</body>
</html>