Code4Scene / assets /chart-interactions.js
KoeYe's picture
Claude Opus 5.5
Draw the charts in the paper figures' kit style
86e4992 verified
Raw History Blame Contribute Delete
3.59 kB
// BuildingBench interaction: full model hit targets, a viewport tooltip, and quieting the other marks.
const detailPromise=fetch(new URL('../data/leaderboard-details.json?v=20261001c',import.meta.url)).then(r=>{if(!r.ok)throw new Error('Leaderboard details unavailable');return r.json();});
const tip=Object.assign(document.createElement('div'),{className:'chart-tooltip',id:'chart-tooltip'});tip.setAttribute('role','tooltip');document.body.append(tip);
let active=null,pinned=false;
function hide(){tip.classList.remove('on');active?.plot.querySelectorAll('.chart-node').forEach(n=>n.classList.remove('dim','hot'));active?.node.removeAttribute('aria-describedby');active=null;pinned=false;}
function show(node,plot,record,anchorSelector){
if(active?.node!==node)hide();active={node,plot,record,anchorSelector};tip.replaceChildren();
const title=document.createElement('strong');title.textContent=record.name;tip.append(title);
const provider=document.createElement('span');provider.className='tooltip-provider';provider.textContent=record.provider;tip.append(provider);
const dl=document.createElement('dl');for(const m of record.metrics){const dt=document.createElement('dt'),dd=document.createElement('dd');dt.textContent=m.label;dd.textContent=(m.currency?'$':'')+String(m.value);dl.append(dt,dd);}tip.append(dl);
tip.classList.add('on');node.setAttribute('aria-describedby','chart-tooltip');plot.querySelectorAll('.chart-node').forEach(n=>{n.classList.toggle('dim',n!==node);n.classList.toggle('hot',n===node);});
const r=(node.querySelector(anchorSelector)||node).getBoundingClientRect(),w=tip.offsetWidth,h=tip.offsetHeight;
tip.style.left=Math.max(8,Math.min(innerWidth-w-8,r.left+r.width/2-w/2))+'px';
tip.style.top=Math.max(8,Math.min(innerHeight-h-8,r.top>h+14?r.top-h-12:r.bottom+12))+'px';
}
export async function bindChartTooltip(node,plot,key,mode,anchorSelector='.bar,.chip'){
const data=await detailPromise,record=data[mode].find(d=>d.key===key||d.name===key);if(!record)return;
bindRecordTooltip(node,plot,record,anchorSelector);
}
// the same behaviour for a chart whose record is not a leaderboard row (the takeaway's family scores)
export function bindRecordTooltip(node,plot,record,anchorSelector='.bar,.chip'){
node.classList.add('chart-node');node.setAttribute('tabindex','0');node.setAttribute('role','button');node.setAttribute('aria-label',record.name+'; '+record.metrics.map(m=>m.label+' '+(m.currency?'$':'')+m.value).join('; '));
node.addEventListener('pointerenter',()=>{pinned=false;show(node,plot,record,anchorSelector);});
node.addEventListener('pointerleave',()=>{if(!pinned&&active?.node===node)hide();});
node.addEventListener('focus',()=>show(node,plot,record,anchorSelector));node.addEventListener('blur',()=>{if(active?.node===node)hide();});
node.addEventListener('click',event=>{event.stopPropagation();show(node,plot,record,anchorSelector);pinned=true;});
node.addEventListener('keydown',event=>{if(event.key==='Escape')hide();if(event.key==='Enter'||event.key===' '){event.preventDefault();show(node,plot,record,anchorSelector);pinned=true;}});
node.dataset.interactive='true';
}
window.addEventListener('scroll',()=>{if(active&&document.activeElement===active.node){const a=active;requestAnimationFrame(()=>{if(active===a)show(a.node,a.plot,a.record,a.anchorSelector);});}else hide();},{passive:true,capture:true});window.addEventListener('resize',hide);document.addEventListener('click',event=>{if(!event.target.closest('.chart-node'))hide();});document.addEventListener('keydown',event=>{if(event.key==='Escape')hide();});